diff --git a/.github/ISSUE_TEMPLATE/bug_feature_question.md b/.github/ISSUE_TEMPLATE/bug_feature_question.md deleted file mode 100644 index 23d24e3..0000000 --- a/.github/ISSUE_TEMPLATE/bug_feature_question.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -name: '🐛 Bug / 💡 Feature / ❓ Question' -about: 'Report a bug, request a feature, or ask a question about BentoPDF' -title: '(Bug) , (Feature) , or (Question) ' -labels: ['needs triage'] -assignees: [] ---- - -## Type of Issue - -Please check one: - -- [ ] 🐛 Bug Report -- [ ] 💡 Feature Request -- [ ] ❓ Question / Help - ---- - -## Description - -Provide a clear and concise description of the issue, feature request, or question. - ---- - -## Steps to Reproduce (for Bugs) - -1. Go to '...' -2. Run '...' -3. Observe error: '...' - -**Expected Behavior:** -Describe what you expected BentoPDF to do. - -**Actual Behavior:** -Describe what actually happened, including error messages. - ---- - -## Feature Request Details (if applicable) - -- What functionality are you requesting? -- Why is this useful? -- Any example or context to illustrate it? - ---- - -## Question Details (if applicable) - -- What is your question? -- What have you tried so far? -- Any relevant code snippet or scenario? - ---- - -## Screenshots / Logs (if applicable) - -Attach any screenshots, logs, or stack traces that help explain the problem or question. - ---- - -## Environment - -- **OS:** (e.g., macOS 14.0 / Ubuntu 22.04 / Windows 11) -- **Dependencies / setup details (if any):** - ---- - -## 💭 Additional Context - -Any other information, suggestions, or references that might help maintainers. - ---- - -✅ **Title Format Reminder:** - -- `(Bug) Text alignment incorrect on multi-line paragraphs` -- `(Feature) Add support for custom PDF metadata` -- `(Question) How to embed custom fonts?` - ---- diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..b638cfd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,122 @@ +name: 🐛 Bug Report +description: Report a bug in BentoPDF +title: "(Bug) " +labels: ["bug", "needs triage"] +body: + - type: markdown + attributes: + value: | + ## ⚠️ Important Notice + **Bug reports without logs or a sample file demonstrating the issue will not be investigated.** + Please help us help you by providing the information needed to reproduce and fix the problem. + + - type: textarea + id: description + attributes: + label: Description + description: Provide a clear and concise description of the bug. + placeholder: What happened? What did you expect to happen? + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to Reproduce + description: How can we reproduce this issue? + placeholder: | + 1. Go to '...' + 2. Click on '...' + 3. Upload file '...' + 4. See error + validations: + required: true + + - type: textarea + id: console-logs + attributes: + label: Console Logs + description: Open browser DevTools (F12 → Console tab) and paste any errors here. + placeholder: Paste console logs here... + render: shell + validations: + required: true + + - type: textarea + id: sample-file + attributes: + label: Sample PDF or File + description: | + Attach a sample PDF that reproduces the issue, or describe how to create one. + If you cannot share the original, create a minimal example that shows the problem. + placeholder: Drag and drop your file here, or describe how to reproduce with any PDF... + validations: + required: true + + - type: dropdown + id: browser + attributes: + label: Browser + description: Which browser are you using? + options: + - Chrome + - Firefox + - Safari + - Edge + - Brave + - Other + validations: + required: true + + - type: input + id: browser-version + attributes: + label: Browser Version + description: e.g., Chrome 120, Firefox 121 + placeholder: "120" + validations: + required: true + + - type: dropdown + id: os + attributes: + label: Operating System + options: + - macOS + - Windows + - Linux + - iOS + - Android + - Other + validations: + required: true + + - type: input + id: bentopdf-version + attributes: + label: BentoPDF Version + description: Check the footer or package.json + placeholder: "1.15.4" + validations: + required: false + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Any other information that might help us debug this issue. + placeholder: Screenshots, network errors, stack traces, etc. + validations: + required: false + + - type: checkboxes + id: checklist + attributes: + label: Pre-submission Checklist + options: + - label: I have included console logs from the browser DevTools + required: true + - label: I have attached a sample file or described how to reproduce the issue + required: true + - label: I have searched existing issues to ensure this is not a duplicate + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..3c041ab --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: 💬 Discord Community + url: https://discord.gg/Bgq3Ay3f2w + about: Join our Discord for quick questions and community support + - name: 📖 Documentation + url: https://github.com/nicholaschen09/BentoPDF#readme + about: Check the README for setup and usage instructions diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..9797c6a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,39 @@ +name: 💡 Feature Request +description: Suggest a new feature for BentoPDF +title: "(Feature) " +labels: ["enhancement", "needs triage"] +body: + - type: textarea + id: description + attributes: + label: Feature Description + description: What functionality are you requesting? + placeholder: Describe the feature you'd like to see... + validations: + required: true + + - type: textarea + id: use-case + attributes: + label: Use Case + description: Why is this feature useful? What problem does it solve? + placeholder: Explain why you need this feature... + validations: + required: true + + - type: textarea + id: examples + attributes: + label: Examples + description: Any examples, mockups, or references to illustrate the feature? + placeholder: Links to similar features, screenshots, etc. + validations: + required: false + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Any other information about the feature request. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 0000000..ac5e905 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,30 @@ +name: ❓ Question +description: Ask a question about BentoPDF +title: "(Question) " +labels: ["question"] +body: + - type: textarea + id: question + attributes: + label: Question + description: What would you like to know? + placeholder: Your question here... + validations: + required: true + + - type: textarea + id: tried + attributes: + label: What have you tried? + description: What solutions have you already attempted? + placeholder: Describe what you've tried so far... + validations: + required: false + + - type: textarea + id: context + attributes: + label: Additional Context + description: Any relevant code snippets, screenshots, or scenarios. + validations: + required: false diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml index 0401832..ee18e97 100644 --- a/.github/workflows/build-and-publish.yml +++ b/.github/workflows/build-and-publish.yml @@ -15,6 +15,8 @@ jobs: if: startsWith(github.ref, 'refs/tags/') permissions: contents: write + env: + HUSKY: 0 steps: - name: Checkout code uses: actions/checkout@v4 @@ -49,10 +51,11 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - docker-build-and-push: + # Build each platform natively in parallel, then merge manifests + build-amd64: runs-on: ubuntu-latest permissions: - contents: write + contents: read packages: write strategy: matrix: @@ -67,9 +70,6 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -86,7 +86,7 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract version and determine release type + - name: Extract version id: version run: | if [[ $GITHUB_REF == refs/tags/v* ]]; then @@ -101,8 +101,7 @@ jobs: echo "is_release=false" >> $GITHUB_OUTPUT fi - # Build and push for releases (with 'latest' tag) - - name: Build and push ${{ matrix.mode.name }} image (release) + - name: Build and push amd64 ${{ matrix.mode.name }} (release) if: steps.version.outputs.is_release == 'true' uses: docker/build-push-action@v6 with: @@ -110,18 +109,13 @@ jobs: build-args: | SIMPLE_MODE=${{ matrix.mode.simple_mode }} tags: | - bentopdf/bentopdf${{ matrix.mode.suffix }}:latest - bentopdf/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version_without_v }} - bentopdf/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }} - ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:latest - ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version_without_v }} - ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }} - platforms: linux/amd64,linux/arm64 - cache-from: type=gha - cache-to: type=gha,mode=max + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 + platforms: linux/amd64 + cache-from: type=gha,scope=amd64-${{ matrix.mode.name }} + cache-to: type=gha,mode=max,scope=amd64-${{ matrix.mode.name }} - # Build and push for main branch (with 'edge' tag) - - name: Build and push ${{ matrix.mode.name }} image (edge) + - name: Build and push amd64 ${{ matrix.mode.name }} (edge) if: steps.version.outputs.is_release == 'false' uses: docker/build-push-action@v6 with: @@ -129,10 +123,178 @@ jobs: build-args: | SIMPLE_MODE=${{ matrix.mode.simple_mode }} tags: | - bentopdf/bentopdf${{ matrix.mode.suffix }}:edge - bentopdf/bentopdf${{ matrix.mode.suffix }}:sha-${{ steps.version.outputs.short_sha }} - ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge - ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:sha-${{ steps.version.outputs.short_sha }} - platforms: linux/amd64,linux/arm64 - cache-from: type=gha - cache-to: type=gha,mode=max + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge-amd64 + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge-amd64 + platforms: linux/amd64 + cache-from: type=gha,scope=amd64-${{ matrix.mode.name }} + cache-to: type=gha,mode=max,scope=amd64-${{ matrix.mode.name }} + + build-arm64: + runs-on: ubuntu-24.04-arm # Native ARM64 runner + permissions: + contents: read + packages: write + strategy: + matrix: + mode: + - name: default + simple_mode: false + suffix: "" + - name: simple + simple_mode: true + suffix: "-simple" + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract version + id: version + run: | + if [[ $GITHUB_REF == refs/tags/v* ]]; then + VERSION=${GITHUB_REF#refs/tags/} + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "version_without_v=${VERSION#v}" >> $GITHUB_OUTPUT + echo "is_release=true" >> $GITHUB_OUTPUT + else + SHORT_SHA=${GITHUB_SHA::7} + echo "version=edge" >> $GITHUB_OUTPUT + echo "short_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT + echo "is_release=false" >> $GITHUB_OUTPUT + fi + + - name: Build and push arm64 ${{ matrix.mode.name }} (release) + if: steps.version.outputs.is_release == 'true' + uses: docker/build-push-action@v6 + with: + push: true + build-args: | + SIMPLE_MODE=${{ matrix.mode.simple_mode }} + tags: | + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64 + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64 + platforms: linux/arm64 + cache-from: type=gha,scope=arm64-${{ matrix.mode.name }} + cache-to: type=gha,mode=max,scope=arm64-${{ matrix.mode.name }} + + - name: Build and push arm64 ${{ matrix.mode.name }} (edge) + if: steps.version.outputs.is_release == 'false' + uses: docker/build-push-action@v6 + with: + push: true + build-args: | + SIMPLE_MODE=${{ matrix.mode.simple_mode }} + tags: | + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge-arm64 + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge-arm64 + platforms: linux/arm64 + cache-from: type=gha,scope=arm64-${{ matrix.mode.name }} + cache-to: type=gha,mode=max,scope=arm64-${{ matrix.mode.name }} + + # Merge manifests after both platforms are built + merge-manifests: + runs-on: ubuntu-latest + needs: [build-amd64, build-arm64] + permissions: + contents: write + packages: write + strategy: + matrix: + mode: + - name: default + suffix: "" + - name: simple + suffix: "-simple" + steps: + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract version + id: version + run: | + if [[ $GITHUB_REF == refs/tags/v* ]]; then + VERSION=${GITHUB_REF#refs/tags/} + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "version_without_v=${VERSION#v}" >> $GITHUB_OUTPUT + echo "is_release=true" >> $GITHUB_OUTPUT + else + SHORT_SHA=${GITHUB_SHA::7} + echo "version=edge" >> $GITHUB_OUTPUT + echo "short_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT + echo "is_release=false" >> $GITHUB_OUTPUT + fi + + - name: Create and push manifest (release) + if: steps.version.outputs.is_release == 'true' + run: | + # DockerHub manifests + docker buildx imagetools create -t bentopdfteam/bentopdf${{ matrix.mode.suffix }}:latest \ + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 \ + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64 + + docker buildx imagetools create -t bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }} \ + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 \ + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64 + + docker buildx imagetools create -t bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version_without_v }} \ + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 \ + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64 + + # GHCR manifests + docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:latest \ + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 \ + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64 + + docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }} \ + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 \ + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64 + + docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version_without_v }} \ + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64 \ + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64 + + - name: Create and push manifest (edge) + if: steps.version.outputs.is_release == 'false' + run: | + # DockerHub manifests + docker buildx imagetools create -t bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge \ + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge-amd64 \ + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge-arm64 + + docker buildx imagetools create -t bentopdfteam/bentopdf${{ matrix.mode.suffix }}:sha-${{ steps.version.outputs.short_sha }} \ + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge-amd64 \ + bentopdfteam/bentopdf${{ matrix.mode.suffix }}:edge-arm64 + + # GHCR manifests + docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge \ + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge-amd64 \ + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge-arm64 + + docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:sha-${{ steps.version.outputs.short_sha }} \ + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge-amd64 \ + ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:edge-arm64 diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml new file mode 100644 index 0000000..8d261dc --- /dev/null +++ b/.github/workflows/sponsors.yml @@ -0,0 +1,12 @@ +name: Update Sponsors +on: + workflow_dispatch: +jobs: + update: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: JamesIves/github-sponsors-readme-action@v1 + with: + token: ${{ secrets.SPONSORS_TOKEN }} + file: 'README.md' \ No newline at end of file diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml new file mode 100644 index 0000000..52ecbd1 --- /dev/null +++ b/.github/workflows/static.yml @@ -0,0 +1,66 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy static content to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + + +# Configure these variables under your repo settings. +# You will likely need to set BASE_URL to be the name of your repo eg 'bentopdf' +env: + SIMPLE_MODE: ${{ vars.SIMPLE_MODE }} + BASE_URL: ${{ vars.BASE_URL }}/ + HUSKY: 0 + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + - name: Install dependencies + run: npm ci + - name: Build distribution + run: | + # export SIMPLE_MODE=${{ vars.SIMPLE_MODE }} + # export BASE_URL=${{ vars.BASE_URL }}/ + npm run build + + - name: Setup Pages + uses: actions/configure-pages@v5 + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + # Upload entire repository + path: dist + name: github-pages-deployment + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + with: + artifact_name: github-pages-deployment diff --git a/.github/workflows/update-embedpdf-snippet.yml b/.github/workflows/update-embedpdf-snippet.yml deleted file mode 100644 index 58ab27a..0000000 --- a/.github/workflows/update-embedpdf-snippet.yml +++ /dev/null @@ -1,135 +0,0 @@ -name: Update EmbedPDF Snippet - -on: - workflow_dispatch: - schedule: - - cron: '0 3 * * 1' # Weekly; adjust as needed - -jobs: - update-snippet: - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Read current upstream version marker - id: current-version - run: | - if [ -f vendor/embedpdf/.upstream-version ]; then - CUR=$(cat vendor/embedpdf/.upstream-version) - else - CUR="" - fi - echo "version=$CUR" >> "$GITHUB_OUTPUT" - - - name: Read latest upstream version (@embedpdf/core) - id: upstream-version - run: | - LATEST=$(npm view @embedpdf/core version) - echo "version=$LATEST" >> "$GITHUB_OUTPUT" - - - name: Should update? - id: gate - run: | - if [ "${{ steps.upstream-version.outputs.version }}" = "${{ steps.current-version.outputs.version }}" ]; then - echo "run=false" >> "$GITHUB_OUTPUT" - echo "No upstream version change detected." - else - echo "run=true" >> "$GITHUB_OUTPUT" - echo "Updating from '${{ steps.current-version.outputs.version }}' to '${{ steps.upstream-version.outputs.version }}'" - fi - - - name: Setup Node - if: steps.gate.outputs.run == 'true' - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: npm - - - name: Enable corepack (pnpm) - if: steps.gate.outputs.run == 'true' - run: corepack enable - - - name: Prepare workspace - if: steps.gate.outputs.run == 'true' - run: | - mkdir -p vendor/embedpdf - npm config set cache ./\.npm-cache - - - name: Clone upstream embed-pdf-viewer - if: steps.gate.outputs.run == 'true' - run: git clone https://github.com/embedpdf/embed-pdf-viewer ../embed-pdf-viewer - - - name: Install upstream deps - if: steps.gate.outputs.run == 'true' - working-directory: ../embed-pdf-viewer - run: pnpm install --frozen-lockfile - - - name: Build snippet - if: steps.gate.outputs.run == 'true' - working-directory: ../embed-pdf-viewer - run: pnpm run build:snippet - - - name: Pack snippet tarball - if: steps.gate.outputs.run == 'true' - working-directory: ../embed-pdf-viewer - run: | - npm pack ./snippet --pack-destination ../bentopdf/vendor/embedpdf - ls -l ../bentopdf/vendor/embedpdf - - - name: Sanitize tarball (rename pkg and pin deps) - if: steps.gate.outputs.run == 'true' - env: - UPSTREAM_VERSION: ${{ steps.upstream-version.outputs.version }} - run: | - TARBALL=$(ls vendor/embedpdf/*.tgz | sort | tail -n1) - TMP=$(mktemp -d) - tar -xzf "$TARBALL" -C "$TMP" - PKG="$TMP/package/package.json" - PKG="$PKG" node - <<'NODE' - const fs = require("fs"); - const path = process.env.PKG; - const ver = process.env.UPSTREAM_VERSION || "1.4.1"; - const pkg = JSON.parse(fs.readFileSync(path, "utf8")); - pkg.name = "embedpdf-snippet"; - pkg.dependencies = pkg.dependencies || {}; - for (const k of Object.keys(pkg.dependencies)) { - if (k.startsWith("@embedpdf/")) pkg.dependencies[k] = `^${ver}`; - if (k === "preact") pkg.dependencies[k] = "^10.17.0"; - } - fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + "\n"); - NODE - NEW=vendor/embedpdf/embedpdf-snippet-${UPSTREAM_VERSION}.tgz - tar -czf "$NEW" -C "$TMP" package - # Remove any older snippet tarballs, keep only the new one - find vendor/embedpdf -maxdepth 1 -name 'embedpdf-snippet-*.tgz' ! -name "$(basename "$NEW")" -delete - rm -rf "$TMP" - ls -l vendor/embedpdf - - - name: Update package.json dependency path - if: steps.gate.outputs.run == 'true' - run: | - TARBALL=$(ls vendor/embedpdf/embedpdf-snippet-*.tgz | sort | tail -n1) - node -e "const fs=require('fs');const pkg=require('./package.json');const tar=process.argv[1];pkg.dependencies['embedpdf-snippet']='file:'+tar;fs.writeFileSync('package.json',JSON.stringify(pkg,null,2)+'\n');" "$TARBALL" - - - name: Refresh lockfile - if: steps.gate.outputs.run == 'true' - run: npm install --package-lock-only - - - name: Write upstream version marker - if: steps.gate.outputs.run == 'true' - run: | - echo "${{ steps.upstream-version.outputs.version }}" > vendor/embedpdf/.upstream-version - - - name: Create Pull Request - if: steps.gate.outputs.run == 'true' - uses: peter-evans/create-pull-request@v6 - with: - commit-message: 'chore: update embedpdf snippet' - title: 'Update vendored EmbedPDF snippet' - body: | - - Build snippet from upstream embed-pdf-viewer via `npm run build:snippet` - - Pack tarball into `vendor/embedpdf/` and point dependency to it - - Refresh package-lock.json - branch: chore/update-embedpdf-snippet - delete-branch: true diff --git a/.gitignore b/.gitignore index 341cb20..74ea119 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,9 @@ dist dist-ssr *.local .npm-cache +.env +.env.production +.env.local # Editor directories and files .vscode/* @@ -27,3 +30,9 @@ dist-ssr coverage/ *.lcov +#backup +.seo-backup +libreoffice-wasm-package + +# helm chart +bentopdf-*.tgz diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..1a21bcc --- /dev/null +++ b/.htaccess @@ -0,0 +1,139 @@ +RewriteEngine On +RewriteBase / + +# ============================================ +# 1. SECURITY HEADERS (UPDATED FOR CDN COMPATIBILITY) +# ============================================ + +Header always set X-Frame-Options "SAMEORIGIN" +Header always set X-Content-Type-Options "nosniff" +Header always set X-XSS-Protection "1; mode=block" +Header always set Referrer-Policy "strict-origin-when-cross-origin" +Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()" +Header always set Cross-Origin-Opener-Policy "same-origin" +Header always set Cross-Origin-Embedder-Policy "require-corp" + + +# ============================================ +# 2. BROWSER CACHING +# ============================================ + +ExpiresActive On +ExpiresByType image/jpeg "access plus 1 year" +ExpiresByType image/png "access plus 1 year" +ExpiresByType image/gif "access plus 1 year" +ExpiresByType image/webp "access plus 1 year" +ExpiresByType image/svg+xml "access plus 1 year" +ExpiresByType image/x-icon "access plus 1 year" +ExpiresByType font/woff2 "access plus 1 year" +ExpiresByType font/woff "access plus 1 year" +ExpiresByType font/ttf "access plus 1 year" +ExpiresByType text/css "access plus 1 month" +ExpiresByType application/javascript "access plus 1 month" +ExpiresByType application/wasm "access plus 1 year" +ExpiresByType application/gzip "access plus 1 year" +ExpiresByType text/html "access plus 0 seconds" + + +# ============================================ +# 3. COMPRESSION (STANDARD) +# ============================================ +SetEnvIfNoCase Request_URI "\.gz$" no-gzip +SetEnvIfNoCase Request_URI "\.br$" no-gzip +SetEnvIfNoCase Request_URI "\.wasm$" no-gzip + + +AddOutputFilterByType DEFLATE text/plain +AddOutputFilterByType DEFLATE text/html +AddOutputFilterByType DEFLATE text/xml +AddOutputFilterByType DEFLATE text/css +AddOutputFilterByType DEFLATE application/xml +AddOutputFilterByType DEFLATE application/xhtml+xml +AddOutputFilterByType DEFLATE application/rss+xml +AddOutputFilterByType DEFLATE application/javascript +AddOutputFilterByType DEFLATE application/x-javascript +AddOutputFilterByType DEFLATE application/json +AddOutputFilterByType DEFLATE image/svg+xml +AddOutputFilterByType DEFLATE font/woff +AddOutputFilterByType DEFLATE font/ttf + + +# ============================================ +# 4. MIME TYPES & SPECIAL FILE HANDLING +# ============================================ +AddType application/javascript .js .mjs +AddType application/wasm .wasm +AddType font/woff2 .woff2 +AddType font/woff .woff +AddType image/webp .webp + + +ForceType application/wasm +Header set Content-Encoding "gzip" +Header set Cross-Origin-Resource-Policy "cross-origin" +Header append Vary Accept-Encoding + + + +ForceType application/octet-stream +Header set Content-Encoding "gzip" +Header append Vary Accept-Encoding + + +# ============================================ +# 5. REDIRECTS & ROUTING +# ============================================ +# Canonical WWW +RewriteCond %{HTTP_HOST} ^bentopdf\.com [NC] +RewriteRule ^(.*)$ https://www.bentopdf.com/$1 [L,R=301] + +# Force HTTPS +RewriteCond %{HTTPS} off +RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] + +# Remove trailing slash (except for language root directories) +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_URI} !^/(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/$ +RewriteCond %{REQUEST_URI} (.+)/$ +RewriteRule ^ %1 [R=301,L] + +# Existing files/dirs - serve directly +RewriteCond %{REQUEST_FILENAME} -f [OR] +RewriteCond %{REQUEST_FILENAME} -d +RewriteRule ^ - [L] + +# ============================================ +# 5.1. LANGUAGE ROUTES (MUST BE BEFORE .html extension rule) +# ============================================ +# English prefix redirects to root +RewriteRule ^en/?$ / [R=301,L] +RewriteRule ^en/(.+)$ /$1 [R=301,L] + +# Language prefix root (e.g., /de/ -> /de/index.html) +RewriteCond %{DOCUMENT_ROOT}/$1/index.html -f +RewriteRule ^(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/?$ /$1/index.html [L] + +# Language prefix with path (e.g., /de/merge-pdf -> /de/merge-pdf.html) +RewriteCond %{DOCUMENT_ROOT}/$1/$2.html -f +RewriteRule ^(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/([^/]+)/?$ /$1/$2.html [L] + +# ============================================ +# 5.5. DOCS ROUTING (VitePress) +# ============================================ +RewriteCond %{REQUEST_URI} ^/docs +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME}\.html -f +RewriteRule ^(.*)$ $1.html [L] + +# ============================================ +# 6. ADD .HTML EXTENSION IF FILE EXISTS (ROOT LEVEL ONLY) +# ============================================ +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_FILENAME}.html -f +RewriteRule ^([^/]+)$ $1.html [L] + +# ============================================ +# 7. ERROR PAGES +# ============================================ +ErrorDocument 404 /404.html diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..2312dc5 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged diff --git a/.well-known/funding-manifest-urls b/.well-known/funding-manifest-urls new file mode 100644 index 0000000..79005d3 --- /dev/null +++ b/.well-known/funding-manifest-urls @@ -0,0 +1 @@ +https://www.bentopdf.com/funding.json diff --git a/404.html b/404.html new file mode 100644 index 0000000..b1a8fbc --- /dev/null +++ b/404.html @@ -0,0 +1,177 @@ + + + + + + + + 404 - Page Not Found | BentoPDF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{> navbar }} + +
+
+ +
+

+ 404 +

+
+ + +

+ Page Not Found +

+ + +

+ Oops! The page you're looking for seems to have wandered off into the + digital void. Don't worry though, our PDF tools are still right where + you left them. +

+ + + + + + +
+
+ + {{> footer }} + + + + + + + + + + diff --git a/Dockerfile b/Dockerfile index 373b41e..7dcd0d5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,13 +7,20 @@ FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ COPY vendor ./vendor -RUN npm ci +ENV HUSKY=0 +RUN npm config set fetch-retries 5 && \ + npm config set fetch-retry-mintimeout 60000 && \ + npm config set fetch-retry-maxtimeout 300000 && \ + npm config set fetch-timeout 600000 && \ + npm ci COPY . . # Build without type checking (vite build only) # Pass SIMPLE_MODE environment variable if provided ARG SIMPLE_MODE=false ENV SIMPLE_MODE=$SIMPLE_MODE +ARG COMPRESSION_MODE=all +ENV COMPRESSION_MODE=$COMPRESSION_MODE # global arg to local arg ARG BASE_URL @@ -29,12 +36,17 @@ RUN if [ -z "$BASE_URL" ]; then \ FROM nginxinc/nginx-unprivileged:stable-alpine-slim LABEL org.opencontainers.image.source="https://github.com/alam00000/bentopdf" +LABEL org.opencontainers.image.url="https://github.com/alam00000/bentopdf" # global arg to local arg ARG BASE_URL +# Set this to "true" to disable Nginx listening on IPv6 +ENV DISABLE_IPV6=false + COPY --chown=nginx:nginx --from=builder /app/dist /usr/share/nginx/html${BASE_URL%/} COPY --chown=nginx:nginx nginx.conf /etc/nginx/nginx.conf +COPY --chown=nginx:nginx --chmod=755 nginx-ipv6.sh /docker-entrypoint.d/99-disable-ipv6.sh RUN mkdir -p /etc/nginx/tmp && chown -R nginx:nginx /etc/nginx/tmp EXPOSE 8080 diff --git a/ICLA.md b/ICLA.md index 48086fb..c80debb 100644 --- a/ICLA.md +++ b/ICLA.md @@ -85,13 +85,13 @@ This Agreement shall be governed by and construed in accordance with the laws of By submitting a pull request or other Contribution to the Project, and by typing your name and date below (or by signing electronically via CLA Assistant), you agree to the terms of this Individual Contributor License Agreement. -**Full Legal Name:** ___________________________ +**Full Legal Name:** Stephan Paternotte -**GitHub Username:** ___________________________ +**GitHub Username:** Stephan-P -**Email Address:** ___________________________ +**Email Address:** stephan@paternottes.net -**Date:** ___________________________ +**Date:** 20-12-2025 **Signature:** ___________________________ diff --git a/README.md b/README.md index 4ea93d0..192e915 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,49 @@ -

+

BentoPDF

**BentoPDF** is a powerful, privacy-first, client-side PDF toolkit that is self hostable and allows you to manipulate, edit, merge, and process PDF files directly in your browser. No server-side processing is required, ensuring your files remain secure and private. -![Docker Pulls](https://img.shields.io/docker/pulls/bentopdf/bentopdf) [![Ko-fi](https://img.shields.io/badge/Buy%20me%20a%20Coffee-yellow?logo=kofi&style=flat-square)](https://ko-fi.com/alio0) ![GitHub Stars](https://img.shields.io/github/stars/alam00000/bentopdf?style=social) +![Docker Pulls](https://img.shields.io/docker/pulls/bentopdfteam/bentopdf) [![Ko-fi](https://img.shields.io/badge/Buy%20me%20a%20Coffee-yellow?logo=kofi&style=flat-square)](https://ko-fi.com/alio01) ![GitHub Stars](https://img.shields.io/github/stars/alam00000/bentopdf?style=social) [![Sponsor me on GitHub](https://img.shields.io/badge/Sponsor-%E2%9D%A4-ff69b4)](https://github.com/sponsors/alam00000) ![BentoPDF Tools](public/images/bentopdf-tools.png) --- +## Table of Contents + +- [Join Us on Discord](#-join-us-on-discord) +- [Documentation](#-documentation) +- [Licensing](#-licensing) +- [Stargazers over time](#-stargazers-over-time) +- [Thank You to Our Sponsors](#-thank-you-to-our-sponsors) +- [Why BentoPDF?](#-why-bentopdf) +- [Features / Tools Supported](#️-features--tools-supported) + - [Organize & Manage PDFs](#organize--manage-pdfs) + - [Edit & Modify PDFs](#edit--modify-pdfs) + - [Convert to PDF](#convert-to-pdf) + - [Convert from PDF](#convert-from-pdf) + - [Secure & Optimize PDFs](#secure--optimize-pdfs) +- [Translations](#-translations) +- [Getting Started](#-getting-started) + - [Prerequisites](#prerequisites) + - [Quick Start](#-quick-start) + - [Static Hosting](#static-hosting-using-netlify-vercel-and-github-pages) + - [Self-Hosting Locally](#-self-hosting-locally) + - [Docker Compose / Podman Compose](#-run-with-docker-compose--podman-compose-recommended) + - [Podman Quadlet](#-podman-quadlet-systemd-integration) + - [Simple Mode](#-simple-mode-for-internal-use) + - [Security Features](#-security-features) + - [Digital Signature CORS Proxy](#digital-signature-cors-proxy-required) + - [Version Management](#-version-management) + - [Development Setup](#-development-setup) +- [Tech Stack & Background](#️-tech-stack--background) +- [Roadmap](#️-roadmap) +- [Contributing](#-contributing) +- [Special Thanks](#special-thanks) + +--- + ## 📢 Join Us on Discord [![Discord](https://img.shields.io/badge/Discord-Join%20Server-7289da?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/Bgq3Ay3f2w) @@ -18,14 +52,38 @@ Have questions, feature requests, or want to chat with the community? Join our D --- +## 📚 Documentation + +[![Documentation](https://img.shields.io/badge/Docs-VitePress-646cff?style=for-the-badge&logo=vite&logoColor=white)](https://bentopdf.com/docs/) + +Visit our [Documentation](https://bentopdf.com/docs/) for: + +- **Getting Started** guide +- **Tools Reference** (50+ tools) +- **Self-Hosting** guides (Docker, Vercel, Netlify, Cloudflare, AWS, Hostinger, Nginx, Apache) +- **Contributing** guide +- **Commercial License** details + +--- + ## 📜 Licensing -BentoPDF is dual-licensed: +BentoPDF is **dual-licensed** to fit your needs: -- **AGPL-3.0** for open-source projects where you share your full source code publicly -- **Commercial License** for proprietary/closed-source applications - **[Get Lifetime License for $49](https://ko-fi.com/s/f32ca4cb75)** (a one-time lifetime purchase, includes all feature updates forever) +| License | Best For | Price | +| -------------- | -------------------------------------------- | ------------------ | +| **AGPL-3.0** | Open-source projects with public source code | **Free** | +| **Commercial** | Proprietary / closed-source applications | **$49** (lifetime) | -For more details, see our [Licensing Page](https://bentopdf.com/licensing.html) +

+ + Get Commercial License + +

+ +> **One-time purchase** · **Unlimited devices & users** · **Lifetime updates** · **No AGPL obligations** + +📖 For more details, see our [Licensing Page](https://bentopdf.com/licensing.html)
@@ -35,6 +93,18 @@ For more details, see our [Licensing Page](https://bentopdf.com/licensing.html) --- +## 💖 Thank You to Our Sponsors + +We're incredibly grateful to all our sponsors and supporters who help keep BentoPDF free and open source! + +[![Sponsor me on GitHub](https://img.shields.io/badge/Become%20a%20Sponsor-%E2%9D%A4-ff69b4?style=for-the-badge)](https://github.com/sponsors/alam00000) +[![Buy me a Coffee](https://img.shields.io/badge/Buy%20me%20a%20Coffee-yellow?style=for-the-badge&logo=kofi)](https://ko-fi.com/alio01) + + + + +--- + ## ✨ Why BentoPDF? - **Privacy First**: All processing happens in your browser. Your files are never uploaded to a server, guaranteeing 100% privacy. @@ -50,67 +120,93 @@ BentoPDF offers a comprehensive suite of tools to handle all your PDF needs. ### Organize & Manage PDFs -| Tool Name | Description | -| :------------------------ | :------------------------------------------------------------------------- | -| **Merge PDFs** | Combine multiple PDF files into one. | -| **Split PDFs** | Extract specific pages or divide a document into smaller files. | -| **Organize Pages** | Reorder, duplicate, or delete pages with a simple drag-and-drop interface. | -| **Extract Pages** | Save a specific range of pages as a new PDF. | -| **Delete Pages** | Remove unwanted pages from your document. | -| **Rotate PDF** | Rotate individual or all pages in a document. | -| **N-Up PDF** | Combine multiple pages onto a single page. | -| **View PDF** | A powerful, integrated PDF viewer. | -| **Alternate & Mix pages** | Merge pages by alternating pages from each PDF. | -| **Posterize PDF** | Split a PDF into multiple smaller pages for print. | -| **PDF Multi Tool** | Merge, Split, Organize, Delete, Rotate, Add Blank Pages, Extract and Duplicate in an unified interface. | -| **Add Attachments** | Embed one or more files into your PDF. | -| **Extract Attachments** | Extract all embedded files from PDF(s) as a ZIP. | -| **Edit Attachments** | View or remove attachments in your PDF. | -| **Divide Pages** | Divide pages horizontally or vertically. | -| **Combine to Single Page**| Stitch all pages into one continuous scroll. | -| **Add Blank Page** | Insert an empty page anywhere in your PDF. | -| **Reverse Pages** | Flip the order of all pages in your document. | -| **View Metadata** | Inspect the hidden properties of your PDF. | -| **PDFs to ZIP** | Package multiple PDF files into a ZIP archive. | -| **Compare PDFs** | Compare two PDFs side by side. | +| Tool Name | Description | +| :--------------------------- | :------------------------------------------------------------------------------------------------------ | +| **Merge PDFs** | Combine multiple PDF files into one. Preserves Bookmarks. | +| **Split PDFs** | Extract specific pages or divide a document into smaller files. | +| **Organize Pages** | Reorder, duplicate, or delete pages with a simple drag-and-drop interface. | +| **Extract Pages** | Save a specific range of pages as a new PDF. | +| **Delete Pages** | Remove unwanted pages from your document. | +| **Rotate PDF** | Rotate individual or all pages in a document. | +| **Rotate by Custom Degrees** | Rotate pages by any custom angle. | +| **N-Up PDF** | Combine multiple pages onto a single page. | +| **View PDF** | A powerful, integrated PDF viewer. | +| **Alternate & Mix Pages** | Merge pages by alternating pages from each PDF. Preserves Bookmarks. | +| **Posterize PDF** | Split a PDF into multiple smaller pages for print. | +| **PDF Multi Tool** | Merge, Split, Organize, Delete, Rotate, Add Blank Pages, Extract and Duplicate in an unified interface. | +| **PDF Booklet** | Rearrange pages for double-sided booklet printing. Fold and staple to create a booklet. | +| **Add Attachments** | Embed one or more files into your PDF. | +| **Extract Attachments** | Extract all embedded files from PDF(s) as a ZIP. | +| **Edit Attachments** | View or remove attachments in your PDF. | +| **Divide Pages** | Divide pages horizontally or vertically. | +| **Combine to Single Page** | Stitch all pages into one continuous scroll. | +| **Add Blank Page** | Insert an empty page anywhere in your PDF. | +| **Reverse Pages** | Flip the order of all pages in your document. | +| **View Metadata** | Inspect the hidden properties of your PDF. | +| **PDFs to ZIP** | Package multiple PDF files into a ZIP archive. | +| **Compare PDFs** | Compare two PDFs side by side. | ### Edit & Modify PDFs -| Tool Name | Description | -| :--------------------- | :---------------------------------------------------------- | -| **PDF Editor** | A comprehensive editor to modify your PDFs. | +| Tool Name | Description | +| :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **PDF Editor** | Annotate, highlight, redact, comment, add shapes/images, search, and view PDFs. | | **Create Fillable Forms** | Create professional fillable PDF forms with text fields, checkboxes, dropdowns, radio buttons, signatures, and more. Fully compliant with PDF standards for compatibility with all PDF viewers. | -| **Add Page Numbers** | Easily add page numbers with customizable formatting. | -| **Add Watermark** | Add text or image watermarks to protect your documents. | -| **Header & Footer** | Add customizable headers and footers. | -| **Crop PDF** | Crop specific pages or the entire document. | -| **Invert Colors** | Invert the colors of your PDF pages for better readability. | -| **Change Background** | Modify the background color of your PDF. | -| **Change Text Color** | Change the color of text content within the PDF. | -| **Fill Forms** | Fill out PDF forms directly in your browser. | -| **Flatten PDF** | Flatten form fields and annotations into static content. | -| **Remove Annotations** | Remove comments, highlights, and other annotations. | -| **Remove Blank Pages** | Auto detect and remove blank pages in a PDF. | -| **Edit Bookmarks** | Add, Edit, Create, Import and Export PDF Bookmarks. | -| **Add Stamps** | Add image stamps to your PDF using the annotation toolbar. | -| **Table of Contents** | Generate a table of contents page from PDF bookmarks. | -| **Redact Content** | Permanently remove sensitive content from your PDFs. | +| **PDF Form Filler** | Fill in forms directly in the browser. Also supports XFA forms. | +| **Add Page Numbers** | Easily add page numbers with customizable formatting. | +| **Add Watermark** | Add text or image watermarks to protect your documents. | +| **Header & Footer** | Add customizable headers and footers. | +| **Crop PDF** | Crop specific pages or the entire document. | +| **Deskew PDF** | Automatically straighten tilted scanned pages using OpenCV. | +| **Font to Outline** | Convert all fonts to vector outlines for consistent rendering across all devices. | +| **Invert Colors** | Invert the colors of your PDF pages for better readability. | +| **Change Background** | Modify the background color of your PDF. | +| **Change Text Color** | Change the color of text content within the PDF. | +| **Flatten PDF** | Flatten form fields and annotations into static content. | +| **Remove Annotations** | Remove comments, highlights, and other annotations. | +| **Remove Blank Pages** | Auto detect and remove blank pages in a PDF. | +| **Edit Bookmarks** | Add, Edit, Create, Import and Export PDF Bookmarks. | +| **Add Stamps** | Add image stamps to your PDF using the annotation toolbar. | +| **Table of Contents** | Generate a table of contents page from PDF bookmarks. | +| **Redact Content** | Permanently remove sensitive content from your PDFs. | ### Convert to PDF -| Tool Name | Description | -| :------------------ | :-------------------------------------------------------------- | -| **Image to PDF** | Convert JPG, PNG, WebP, SVG, BMP, HEIC, and TIFF images to PDF. | -| **JPG to PDF** | Convert JPG images to PDF. | -| **PNG to PDF** | Convert PNG images to PDF. | -| **WebP to PDF** | Convert WebP images to PDF. | -| **SVG to PDF** | Convert SVG images to PDF. | -| **BMP to PDF** | Convert BMP images to PDF. | -| **HEIC to PDF** | Convert HEIC images to PDF. | -| **TIFF to PDF** | Convert TIFF images to PDF. | -| **Markdown to PDF** | Convert `.md` files into professional PDF documents. | -| **Text to PDF** | Convert plain text files into a PDF. | -| **JSON to PDF** | Convert JSON to PDF. | +| Tool Name | Description | +| :-------------------- | :----------------------------------------------------------------------------------------------------- | +| **Image to PDF** | Convert JPG, PNG, BMP, GIF, TIFF, PNM, PGM, PBM, PPM, PAM, JXR, JPX, JP2, PSD, SVG, HEIC, WebP to PDF. | +| **JPG to PDF** | Convert JPG, JPEG, and JPEG2000 (JP2/JPX) images to PDF. | +| **PNG to PDF** | Convert PNG images to PDF. | +| **WebP to PDF** | Convert WebP images to PDF. | +| **SVG to PDF** | Convert SVG images to PDF. | +| **BMP to PDF** | Convert BMP images to PDF. | +| **HEIC to PDF** | Convert HEIC images to PDF. | +| **TIFF to PDF** | Convert TIFF images to PDF. | +| **PSD to PDF** | Convert Adobe Photoshop (PSD) files to PDF. | +| **Word to PDF** | Convert Word documents (DOCX, DOC, ODT, RTF) to PDF. | +| **Excel to PDF** | Convert Excel spreadsheets (XLSX, XLS, ODS, CSV) to PDF. | +| **PowerPoint to PDF** | Convert PowerPoint presentations (PPTX, PPT, ODP) to PDF. | +| **ODT to PDF** | Convert OpenDocument Text files to PDF. | +| **ODS to PDF** | Convert OpenDocument Spreadsheet (ODS) files to PDF. | +| **ODP to PDF** | Convert OpenDocument Presentation (ODP) files to PDF. | +| **ODG to PDF** | Convert OpenDocument Graphics (ODG) files to PDF. | +| **RTF to PDF** | Convert Rich Text Format documents to PDF. | +| **CSV to PDF** | Convert CSV spreadsheet files to PDF. | +| **Markdown to PDF** | Write or paste Markdown and export it as a beautifully formatted PDF. | +| **Text to PDF** | Convert plain text files into a PDF. | +| **JSON to PDF** | Convert JSON files to PDF. | +| **XML to PDF** | Convert XML documents to PDF. | +| **EPUB to PDF** | Convert EPUB e-books to PDF. | +| **MOBI to PDF** | Convert MOBI e-books to PDF. | +| **FB2 to PDF** | Convert FictionBook (FB2) e-books to PDF. | +| **CBZ to PDF** | Convert comic book archives (CBZ/CBR) to PDF. | +| **XPS to PDF** | Convert XPS/OXPS documents to PDF. | +| **Email to PDF** | Convert email files (EML, MSG) to PDF. Supports Outlook exports. | +| **Pages to PDF** | Convert Apple Pages documents to PDF. | +| **WPD to PDF** | Convert WordPerfect documents (WPD) to PDF. | +| **WPS to PDF** | Convert WPS Office documents to PDF. | +| **PUB to PDF** | Convert Microsoft Publisher (PUB) files to PDF. | +| **VSD to PDF** | Convert Microsoft Visio (VSD, VSDX) files to PDF. | ### Convert from PDF @@ -122,28 +218,35 @@ BentoPDF offers a comprehensive suite of tools to handle all your PDF needs. | **PDF to WebP** | Convert each PDF page into a WebP image. | | **PDF to BMP** | Convert each PDF page into a BMP image. | | **PDF to TIFF** | Convert each PDF page into a TIFF image. | +| **PDF to SVG** | Convert each page into a scalable vector graphic (SVG) for perfect quality. | | **PDF to Greyscale** | Convert a color PDF into a black-and-white version. | -| **OCR PDF** | Make scanned PDFs searchable and copyable using Optical Character Recognition. | +| **PDF to Text** | Extract text from PDF files and save as plain text (.txt). | | **PDF to JSON** | Convert PDF files to JSON format. | +| **PDF to CSV** | Extract tables from PDF and convert to CSV format. | +| **PDF to Excel** | Extract tables from PDF and convert to Excel (XLSX) format. | +| **Extract Tables** | Extract tables from PDF files and export as CSV, JSON, or Markdown. | +| **OCR PDF** | Make scanned PDFs searchable and copyable using Optical Character Recognition. | ### Secure & Optimize PDFs -| Tool Name | Description | -| :--------------------- | :----------------------------------------------------------------- | -| **Compress PDF** | Reduce file size while maintaining quality. | -| **Repair PDF** | Attempt to repair and recover data from a corrupted PDF. | -| **Encrypt PDF** | Add a password to protect your PDF from unauthorized access. | -| **Decrypt PDF** | Remove password protection from a PDF (password required). | -| **Change Permissions** | Set or modify user permissions for printing, copying, and editing. | -| **Sign PDF** | Add your digital signature to a document. | -| **Redact Content** | Permanently remove sensitive content from your PDFs. | -| **Edit Metadata** | View and modify PDF metadata (author, title, keywords, etc.). | -| **Remove Metadata** | Strip all metadata from your PDF for privacy. | -| **Linearize PDF** | Optimize PDF for fast web view. | -| **Sanitize PDF** | Remove potentially unwanted or malicous files from PDF. | -| **Fix Page Size** | Standardize all pages to a uniform size. | -| **Page Dimensions** | Analyze page size, orientation, and units. | -| **Remove Restrictions**| Remove password protection and security restrictions associated with digitally signed PDF files. | +| Tool Name | Description | +| :---------------------- | :--------------------------------------------------------------------------------------------------------- | +| **Compress PDF** | Reduce file size while maintaining quality. | +| **Repair PDF** | Attempt to repair and recover data from a corrupted PDF. | +| **Encrypt PDF** | Add a password to protect your PDF from unauthorized access. | +| **Decrypt PDF** | Remove password protection from a PDF (password required). | +| **Change Permissions** | Set or modify user permissions for printing, copying, and editing. | +| **Sign PDF** | Draw, type, or upload your signature. | +| **Digital Signature** | Add cryptographic digital signatures using X.509 certificates (PFX/PEM). Private key never leaves browser. | +| **Validate Signature** | Verify digital signatures, check certificate validity, and confirm document integrity. | +| **Redact Content** | Permanently remove sensitive content from your PDFs. | +| **Edit Metadata** | View and modify PDF metadata (author, title, keywords, etc.). | +| **Remove Metadata** | Strip all metadata from your PDF for privacy. | +| **Linearize PDF** | Optimize PDF for fast web viewing. | +| **Sanitize PDF** | Remove metadata, annotations, scripts, and more. | +| **Fix Page Size** | Standardize all pages to a uniform size. | +| **Page Dimensions** | Analyze page size, orientation, and units. | +| **Remove Restrictions** | Remove password protection and security restrictions associated with digitally signed PDF files. | --- @@ -151,11 +254,18 @@ BentoPDF offers a comprehensive suite of tools to handle all your PDF needs. BentoPDF is available in multiple languages: -| Language | Status | -|----------|--------| -| English | [![English](https://img.shields.io/badge/Complete-green?style=flat-square)](public/locales/en/common.json) | -| German | [![German](https://img.shields.io/badge/In_Progress-yellow?style=flat-square)](public/locales/de/common.json) | -| Vietnamese | [![Vietnamese](https://img.shields.io/badge/Complete-green?style=flat-square)](public/locales/vi/common.json) | +| Language | Status | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| English | [![English](https://img.shields.io/badge/Complete-green?style=flat-square)](public/locales/en/common.json) | +| Chinese | [![Chinese](https://img.shields.io/badge/Complete-green?style=flat-square)](public/locales/zh/common.json) | +| Traditional Chinese | [![Traditional Chinese](https://img.shields.io/badge/Complete-green?style=flat-square)](public/locales/zh-TW/common.json) | +| French | [![French](https://img.shields.io/badge/Complete-green?style=flat-square)](public/locales/fr/common.json) | +| German | [![German](https://img.shields.io/badge/Complete-green?style=flat-square)](public/locales/de/common.json) | +| Indonesian | [![Indonesian](https://img.shields.io/badge/Complete-green?style=flat-square)](public/locales/id/common.json) | +| Italian | [![Italian](https://img.shields.io/badge/Complete-green?style=flat-square)](public/locales/it/common.json) | +| Portuguese | [![Portuguese](https://img.shields.io/badge/Complete-green?style=flat-square)](public/locales/pt/common.json) | +| Turkish | [![Turkish](https://img.shields.io/badge/Complete-green?style=flat-square)](public/locales/tr/common.json) | +| Vietnamese | [![Vietnamese](https://img.shields.io/badge/Complete-green?style=flat-square)](public/locales/vi/common.json) | Want to help translate BentoPDF into your language? Check out our [Translation Guide](TRANSLATION.md)! @@ -171,22 +281,9 @@ You can run BentoPDF locally for development or personal use. - [npm](https://www.npmjs.com/) (or yarn/pnpm) - [Docker](https://www.docker.com/) & [Docker Compose](https://docs.docker.com/compose/install/) (for containerized setup) -### 🚀 Quick Start with Docker +### 🚀 Quick Start -[![Deploy on Zeabur](https://zeabur.com/button.svg)](https://zeabur.com/templates/K4AU2B) - -You can run BentoPDF directly from Docker Hub or GitHub Container Registry without cloning the repository: - -You can also watch the video on how to set it up 👉 -[BentoPDF Docker Setup](https://drive.google.com/file/d/1C4eJ2nqeaH__1Tlad-xuBHaF2Ha4fSBf/view?usp=drive_link) - -**Using Docker Hub:** - -```bash -docker run -p 3000:8080 bentopdf/bentopdf:latest -``` - -**Using GitHub Container Registry:** +Run BentoPDF instantly from GitHub Container Registry (Recommended): ```bash docker run -p 3000:8080 ghcr.io/alam00000/bentopdf:latest @@ -194,9 +291,36 @@ docker run -p 3000:8080 ghcr.io/alam00000/bentopdf:latest Open your browser at: http://localhost:3000 -This is the fastest way to try BentoPDF without setting up a development environment. +
+Alternative: Using Docker Hub or Podman -### 🏠 Self-Hosting +**Docker Hub:** + +```bash +docker run -p 3000:8080 bentopdfteam/bentopdf:latest +``` + +**Podman (GHCR):** + +```bash +podman run -p 3000:8080 ghcr.io/alam00000/bentopdf:latest +``` + +**Podman (Docker Hub):** + +```bash +podman run -p 3000:8080 docker.io/bentopdfteam/bentopdf:latest +``` + +> **Note:** All `docker` commands in this documentation work with Podman by replacing `docker` with `podman`. + +
+ +### Static Hosting using Netlify, Vercel, and GitHub Pages + +It is very straightforward to host your own instance of BentoPDF using a static web page hosting service. Plus, services such as Netlify, Vercel, and GitHub Pages all offer a free tier for getting started. See [Static Hosting](https://github.com/alam00000/bentopdf/blob/main/STATIC-HOSTING.md) for details. + +### 🏠 Self-Hosting Locally Since BentoPDF is fully client-side, all processing happens in the user's browser and no server-side processing is required. This means you can host BentoPDF as simple static files on any web server or hosting platform. @@ -208,7 +332,7 @@ The easiest way to self-host is to download the pre-built distribution file from 2. Download the latest `dist-{version}.zip` file 3. Extract the zip file 4. Serve the extracted folder with your preferred web server - + **Serve the extracted folder (requires Node.js):** ```bash @@ -248,6 +372,53 @@ npm run preview ``` +**Compression Modes:** + +BentoPDF supports different compression modes for optimized builds: + +```bash +# Gzip only (smallest Docker image size) +npm run build:gzip +docker build --build-arg COMPRESSION_MODE=g -t bentopdf:gzip . + +# Brotli only (best compression ratio) +npm run build:brotli +docker build --build-arg COMPRESSION_MODE=b -t bentopdf:brotli . + +# No compression (fastest build time) +npm run build:original +docker build --build-arg COMPRESSION_MODE=o -t bentopdf:original . + +# All formats (default, maximum browser compatibility) +npm run build:all +docker build --build-arg COMPRESSION_MODE=all -t bentopdf:all . +``` + +| Mode | Files Kept | Use Case | +| ----- | ----------- | --------------------------------- | +| `g` | `.gz` only | Standard nginx or minimal size | +| `b` | `.br` only | Modern CDN with Brotli support | +| `o` | originals | Development or custom compression | +| `all` | all formats | Maximum compatibility (default) | + +**CDN Optimization:** + +BentoPDF can use jsDelivr CDN to serve large WASM files (LibreOffice, Ghostscript, PyMuPDF) for improved performance and reduced bandwidth costs: + +```bash +# Production build with CDN (Recommended) +VITE_USE_CDN=true npm run build + +# Standard build with local files only +npm run build +``` + +**How it works:** + +- When `VITE_USE_CDN=true`: Browser loads WASM files from jsDelivr CDN (fast, global delivery) +- Local files are **always included** as automatic fallback +- If CDN fails then it falls back to local files + **Subdirectory Hosting:** BentoPDF can also be hosted from a subdirectory (e.g., `example.com/tools/bentopdf/`): @@ -269,7 +440,7 @@ cp -r dist/* serve-test/tools/bentopdf/ npx serve serve-test ``` -The website can be accessible at: ```http://localhost:3000/tools/bentopdf/``` +The website can be accessible at: `http://localhost:3000/tools/bentopdf/` The `npm run package` command creates a `dist-{version}.zip` file that you can use for self-hosting. @@ -299,11 +470,12 @@ docker build \ docker run -p 3000:8080 bentopdf-simple ``` -> **Important**: +> **Important**: +> > - Always include trailing slashes in `BASE_URL` (e.g., `/bentopdf/` not `/bentopdf`) > - The default value is `/` for root deployment -### 🚀 Run with Docker Compose (Recommended) +### 🚀 Run with Docker Compose / Podman Compose (Recommended) For a more robust setup with auto-restart capabilities: @@ -312,7 +484,8 @@ For a more robust setup with auto-restart capabilities: ```yaml services: bentopdf: - image: bentopdf/bentopdf:latest + image: ghcr.io/alam00000/bentopdf:latest # Recommended + # image: bentopdfteam/bentopdf:latest # Alternative: Docker Hub container_name: bentopdf ports: - '3000:8080' @@ -322,11 +495,48 @@ services: 2. **Start the application**: ```bash +# Docker Compose docker-compose up -d + +# Podman Compose +podman-compose up -d ``` The application will be available at `http://localhost:3000`. +### 🐧 Podman Quadlet (Systemd Integration) + +For Linux production deployments, you can run BentoPDF as a systemd service using [Podman Quadlet](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html). + +Create `~/.config/containers/systemd/bentopdf.container`: + +```ini +[Unit] +Description=BentoPDF - Privacy-first PDF toolkit +After=network-online.target + +[Container] +Image=ghcr.io/alam00000/bentopdf:latest +ContainerName=bentopdf +PublishPort=3000:8080 +AutoUpdate=registry + +[Service] +Restart=always + +[Install] +WantedBy=default.target +``` + +Then enable and start: + +```bash +systemctl --user daemon-reload +systemctl --user enable --now bentopdf +``` + +For detailed Quadlet configuration, see [Self-Hosting Docker Guide](https://bentopdf.com/docs/self-hosting/docker). + ### 🏢 Simple Mode for Internal Use For organizations that want a clean, distraction-free interface focused solely on PDF tools, BentoPDF supports a **Simple Mode** that hides all branding and marketing content. @@ -357,22 +567,109 @@ docker run -p 8080:8080 bentopdf For detailed security configuration, see [SECURITY.md](SECURITY.md). +### Digital Signature CORS Proxy (Required) + +The **Digital Signature** tool uses a signing library that may need to fetch certificate chain data from certificate authority provider. Since many certificate servers don't include CORS headers, a proxy is required for this feature to work in the browser. + +**When is the proxy needed?** + +- Only when using the Digital Signature tool +- Only if your certificate requires fetching issuer certificates from external URLs +- Self-signed certificates typically don't need this + +**Deploying the CORS Proxy (Cloudflare Workers):** + +1. **Navigate to the cloudflare directory:** + + ```bash + cd cloudflare + ``` + +2. **Login to Cloudflare (if not already):** + + ```bash + npx wrangler login + ``` + +3. **Deploy the worker:** + + ```bash + npx wrangler deploy + ``` + +4. **Note your worker URL** (e.g., `https://bentopdf-cors-proxy.your-subdomain.workers.dev`) + +5. **Set the environment variable when building:** + ```bash + VITE_CORS_PROXY_URL=https://your-worker-url.workers.dev npm run build + ``` + +#### Production Security Features + +The CORS proxy includes several security measures: + +| Feature | Description | +| ----------------------- | ------------------------------------------------------------------------- | +| **URL Restrictions** | Only allows certificate URLs (`.crt`, `.cer`, `.pem`, `/certs/`, `/ocsp`) | +| **Private IP Blocking** | Blocks requests to localhost, 10.x, 192.168.x, 172.16-31.x | +| **File Size Limit** | Rejects files larger than 10MB | +| **Rate Limiting** | 60 requests per IP per minute (requires KV) | +| **HMAC Signatures** | Optional client-side signing (limited protection) | + +#### Enabling Rate Limiting (Recommended) + +Rate limiting requires Cloudflare KV storage: + +```bash +cd cloudflare + +# Create KV namespace +npx wrangler kv namespace create "RATE_LIMIT_KV" + +# Copy the returned ID and add to wrangler.toml: +# [[kv_namespaces]] +# binding = "RATE_LIMIT_KV" +# id = "YOUR_ID_HERE" + +# Redeploy +npx wrangler deploy +``` + +**Free tier limits:** 100,000 reads/day, 1,000 writes/day (~300-500 signatures/day) + +#### HMAC Signature Verification (Optional) + +> **⚠️ Security Warning:** Client-side secrets can be extracted from bundled JavaScript. For production deployments with sensitive requirements, use your own backend server to proxy requests instead of embedding secrets in frontend code. + +BentoPDF uses client-side HMAC as a deterrent against casual abuse, but accepts this tradeoff due to its fully client-side architecture. To enable: + +```bash +# Generate a secret +openssl rand -hex 32 + +# Set on Cloudflare Worker +npx wrangler secret put PROXY_SECRET + +# Set in build environment +VITE_CORS_PROXY_SECRET=your-secret npm run build +``` + ### 📦 Version Management -BentoPDF supports semantic versioning with multiple Docker tags available on both Docker Hub and GitHub Container Registry: +BentoPDF supports semantic versioning with multiple container tags available: -**Docker Hub:** - -- **Latest**: `bentopdf/bentopdf:latest` -- **Specific Version**: `bentopdf/bentopdf:1.0.0` -- **Version with Prefix**: `bentopdf/bentopdf:v1.0.0` - -**GitHub Container Registry:** +**GitHub Container Registry (Recommended):** - **Latest**: `ghcr.io/alam00000/bentopdf:latest` - **Specific Version**: `ghcr.io/alam00000/bentopdf:1.0.0` - **Version with Prefix**: `ghcr.io/alam00000/bentopdf:v1.0.0` +**Docker Hub:** + +- **Latest**: `bentopdfteam/bentopdf:latest` +- **Specific Version**: `bentopdfteam/bentopdf:1.0.0` +- **Version with Prefix**: `bentopdfteam/bentopdf:v1.0.0` + #### Quick Release ```bash @@ -476,6 +773,33 @@ We welcome contributions from the community! Here's how you can get started: Have an idea for a new tool or an improvement? [Open an issue](https://github.com/alam00000/bentopdf/issues) to discuss it first. +### 📖 Contributing to Documentation + +Our documentation is built with [VitePress](https://vitepress.dev/). Here's how to contribute: + +```bash +# Install dependencies +npm install + +# Start docs dev server +npm run docs:dev + +# Build docs for production +npm run docs:build + +# Preview the built docs +npm run docs:preview +``` + +Documentation files are in the `docs/` folder: + +- `docs/index.md` - Home page +- `docs/getting-started.md` - Getting started guide +- `docs/tools/` - Tools reference +- `docs/self-hosting/` - Self-hosting guides (Docker, Vercel, Netlify, Hostinger, etc.) +- `docs/contributing.md` - Contributing guide +- `docs/licensing.md` - Commercial license info + --- ## Special Thanks @@ -491,5 +815,8 @@ BentoPDF wouldn't be possible without the amazing open-source tools and librarie - **[Tailwind CSS](https://tailwindcss.com/)** – For rapid, flexible, and beautiful UI styling. - **[qpdf](https://github.com/qpdf/qpdf)** and **[qpdf-wasm](https://github.com/neslinesli93/qpdf-wasm)**– A powerful command-line tool and library for inspecting, repairing, and transforming PDF file ported to wasm - **[cpdf](https://www.coherentpdf.com/)** – For content preserving pdf operations. +- **[LibreOffice](https://www.libreoffice.org/)** – For powerful document conversion capabilities. +- **[PyMuPDF](https://github.com/pymupdf/PyMuPDF)** – For high-performance PDF manipulation and data extraction. +- **[Ghostscript(GhostPDL)](https://github.com/ArtifexSoftware/ghostpdl)** – Needs no Introduction. Your work inspires and empowers developers everywhere. Thank you for making open-source amazing! diff --git a/RELEASE.md b/RELEASE.md index 88d0c78..106165b 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -215,16 +215,16 @@ git reset --hard HEAD~1 1. **GitHub Actions Triggered**: Workflow starts building Docker image 2. **Docker Build**: Multi-architecture image created 3. **Docker Push**: Images pushed to Docker Hub with tags: - - `bentopdf/bentopdf:latest` - - `bentopdf/bentopdf:1.0.1` - - `bentopdf/bentopdf:v1.0.1` + - `bentopdfteam/bentopdf:latest` + - `bentopdfteam/bentopdf:1.0.1` + - `bentopdfteam/bentopdf:v1.0.1` ### **End Result:** Users can immediately pull your new version: ```bash -docker pull bentopdf/bentopdf:1.0.1 +docker pull bentopdfteam/bentopdf:1.0.1 ``` --- diff --git a/SIMPLE_MODE.md b/SIMPLE_MODE.md index 996caef..4dd45d6 100644 --- a/SIMPLE_MODE.md +++ b/SIMPLE_MODE.md @@ -23,27 +23,35 @@ When enabled, Simple Mode will: Use the pre-built Simple Mode image directly: +**Using GitHub Container Registry (Recommended):** + +```bash +# Docker +docker run -p 3000:8080 ghcr.io/alam00000/bentopdf-simple:latest + +# Podman +podman run -p 3000:8080 ghcr.io/alam00000/bentopdf-simple:latest +``` + **Using Docker Hub:** ```bash -docker run -p 3000:8080 bentopdf/bentopdf-simple:latest +# Docker +docker run -p 3000:8080 bentopdfteam/bentopdf-simple:latest + +# Podman +podman run -p 3000:8080 docker.io/bentopdfteam/bentopdf-simple:latest ``` -**Using GitHub Container Registry:** - -```bash -docker run -p 3000:8080 ghcr.io/alam00000/bentopdf-simple:latest -``` - -Or with Docker Compose: +Or with Docker Compose / Podman Compose: ```yaml services: bentopdf: - # Using Docker Hub - image: bentopdf/bentopdf-simple:latest - # Or using GitHub Container Registry - # image: ghcr.io/alam00000/bentopdf-simple:latest + # Using GitHub Container Registry (Recommended) + image: ghcr.io/alam00000/bentopdf-simple:latest + # Or using Docker Hub + # image: bentopdfteam/bentopdf-simple:latest container_name: bentopdf restart: unless-stopped ports: @@ -105,9 +113,13 @@ This automatically builds and serves Simple Mode on `http://localhost:3000`. ### Method 2: Using Pre-built Image (Easiest for Production) ```bash -# Pull and run the Simple Mode image -docker pull bentopdf/bentopdf-simple:latest -docker run -p 3000:8080 bentopdf/bentopdf-simple:latest +# Docker - Pull and run the Simple Mode image +docker pull ghcr.io/alam00000/bentopdf-simple:latest +docker run -p 3000:8080 ghcr.io/alam00000/bentopdf-simple:latest + +# Podman +podman pull ghcr.io/alam00000/bentopdf-simple:latest +podman run -p 3000:8080 ghcr.io/alam00000/bentopdf-simple:latest ``` Open `http://localhost:3000` in your browser. @@ -127,11 +139,13 @@ Open `http://localhost:3000` in your browser. ### Method 4: Compare Both Modes ```bash -# Test Normal Mode -docker run -p 3000:8080 bentopdf/bentopdf:latest +# Test Normal Mode (Docker) +docker run -p 3000:8080 ghcr.io/alam00000/bentopdf:latest -# Test Simple Mode -docker run -p 3001:8080 bentopdf/bentopdf-simple:latest +# Test Simple Mode (Docker) +docker run -p 3001:8080 ghcr.io/alam00000/bentopdf-simple:latest + +# Podman users: replace 'docker' with 'podman' ``` - Normal Mode: `http://localhost:3000` @@ -149,52 +163,82 @@ When Simple Mode is working correctly, you should see: - ❌ No hero section with "The PDF Toolkit built for privacy" - ❌ No features, FAQ, testimonials, or footer sections -## 📦 Available Docker Images +## 📦 Available Container Images ### Normal Mode (Full Branding) -**Docker Hub:** - -- `bentopdf/bentopdf:latest` -- `bentopdf/bentopdf:v1.0.0` (versioned) - -**GitHub Container Registry:** +**GitHub Container Registry (Recommended):** - `ghcr.io/alam00000/bentopdf:latest` - `ghcr.io/alam00000/bentopdf:v1.0.0` (versioned) -### Simple Mode (Clean Interface) - **Docker Hub:** -- `bentopdf/bentopdf-simple:latest` -- `bentopdf/bentopdf-simple:v1.0.0` (versioned) +- `bentopdfteam/bentopdf:latest` +- `bentopdfteam/bentopdf:v1.0.0` (versioned) -**GitHub Container Registry:** +### Simple Mode (Clean Interface) + +**GitHub Container Registry (Recommended):** - `ghcr.io/alam00000/bentopdf-simple:latest` - `ghcr.io/alam00000/bentopdf-simple:v1.0.0` (versioned) +**Docker Hub:** + +- `bentopdfteam/bentopdf-simple:latest` +- `bentopdfteam/bentopdf-simple:v1.0.0` (versioned) + ## 🚀 Production Deployment Examples -### Internal Company Tool +### Docker Compose / Podman Compose ```yaml services: bentopdf: - image: bentopdf/bentopdf-simple:latest + image: ghcr.io/alam00000/bentopdf-simple:latest # Recommended + # image: bentopdfteam/bentopdf-simple:latest # Alternative: Docker Hub container_name: bentopdf restart: unless-stopped ports: - - '80:80' + - '80:8080' environment: - PUID=1000 - PGID=1000 ``` +### Podman Quadlet (Linux Systemd) + +Create `~/.config/containers/systemd/bentopdf-simple.container`: + +```ini +[Unit] +Description=BentoPDF Simple Mode +After=network-online.target + +[Container] +Image=ghcr.io/alam00000/bentopdf-simple:latest +ContainerName=bentopdf-simple +PublishPort=80:8080 +AutoUpdate=registry + +[Service] +Restart=always + +[Install] +WantedBy=default.target +``` + +Enable and start: + +```bash +systemctl --user daemon-reload +systemctl --user enable --now bentopdf-simple +``` + ## ⚠️ Important Notes -- **Pre-built images**: Use `bentopdf/bentopdf-simple:latest` for Simple Mode +- **Pre-built images**: Use `ghcr.io/alam00000/bentopdf-simple:latest` for Simple Mode (recommended) - **Environment variables**: `SIMPLE_MODE=true` only works during build, not runtime - **Build-time optimization**: Simple Mode uses dead code elimination for smaller bundles - **Same functionality**: All PDF tools work identically in both modes diff --git a/STATIC-HOSTING.md b/STATIC-HOSTING.md new file mode 100644 index 0000000..9cbb82b --- /dev/null +++ b/STATIC-HOSTING.md @@ -0,0 +1,63 @@ +# Hosting BentoPDF as a static website + +As an alternative to runnning BenotPDF locally or in a Docker container, you can very easily host it as a set of static web pages. Here are a few examples: + +## Netlify + +### Netlify - static deployment + +One of simplest ways to host BentoPDF is to create a project at [Netlify](https://www.netlify.com/) and create a static deployment. You can accomplish this by first downloading the pre-built distribution file from our [GitHub releases](https://github.com/alam00000/bentopdf/releases). Each release includes a `dist-{version}.zip` file that contains all necessary files for self-hosting. + +1. Go to [BentoPDF Releases](https://github.com/alam00000/bentopdf/releases) +2. Download the latest `dist-{version}.zip` file +3. Next, if you have not already done so, create a Netlify account and log in. +4. From your Netlify projects page, add a new project and select "Deploy manually". +5. Drag and drop to upload the Bentopdf zip file you downloaded in step 3. +6. Your BentoPDF deployment should now be working! Optionally, you can go into Project Configuration and change the project name. + +When a new BentoPDF release becomes available, you will need to repeat steps 1-3, then go into "Deploys" and upload the new release. + +### Netlify - dynamic deployment + +Alternatively, you can configure a Netlify project to automatically deploy whenever your BentoPDF is updated. + +1. If you have not done so already, create a fork of BentoPDF into your own Github account. +2. If you have not already done so, create a Netlify account and log in. +3. From your Netlify projects page, add a new project and select 'Import an existing project'. +4. Select the GitHub button, authorize Netlify, then choose where to install the integration. You can choose 'All repositories' or 'Only select repositories' and choose your BentoPDF fork. +5. Select your repo and give it a project name. (add environment variables?) Then click the blue 'Deploy' button. +6. The Netlify build & deploy process will kick off. Once it finishes, you can click on the provided URL `https://[projectname]/netlify.app` to view your deployment of BentoPDF. + +Whenever the BentoPDF source code is updated, you can sync the changes into your repo. This will kick off a new build and deploy within Netlify. + +If you want to use BentoPDF's simple mode, go into Deploy Settings, then Environment Variables, and Add a variable. Add `SIMPLE_MODE` and set it to `true`. You will need to manually kick a new build to get this to take effect. + +## Vercel + +Vercel provides similar services to Netlify dynamic hosting. + +1. If you have not done so already, create a fork of BentoPDF into your own Github account. +2. If you have not already done so, create a Vercel account and log in. +3. From your Vercel Overview page, select 'Add new project' +4. Under 'Import Git Repository' and then choose 'Add GitHub Account'. Follow the prompts to authorize Vercel integration. You can choose 'All repositories' or 'Only select repositories' and choose your BentoPDF fork. +5. Select 'Import' to import the repo into Vercel. +6. Under 'Framework Preset', select 'Vite' and save the settings. +7. The Vercel build & deploy process will kick off. Once it finishes, you can click on the provided link to view your deployment of BentoPDF. + +Whenever the BentoPDF source code is updated, you can sync the changes into your repo. This will kick off a new build and deploy within BentoPDF. + +If you want to use BentoPDF's simple mode, go into Project Settings, then Environment Variables, and Create a new variable. Add `SIMPLE_MODE` and set it to `true`. You will need to redeploy to get this to take effect. + +## GitHub Pages + +You can also host your own instance of BentoPDF using GitHub pages. An advantage of this over the other options is you are able to do everything in GitHub without any third party service. + +1. If you have not done so already, create a fork of BentoPDF into your own Github account. +2. From your fork, go to `Settings->Pages`, and change the 'Source' to 'GitHub Actions' +3. Go to `Settings->Secrets and Variables > Actions`, then select 'Variables', and add the repository variable `BASE_URL`. Set the value to `/bentopdf`. *If you've renamed the repo to something other than bentopdf, put that here*. +4. Go to `Actions` in the top menu, and select 'I understand' to enable Actions +5. Within Actions, on the left, select 'Deploy static content to Pages', and then on the right select 'Run workflow', and in the dropdown, 'Run Workflow'. The action will not run to build BentoPDF and deploy it to GitHub Pages. + +When the build completes, you can find the website at `https://[your-github-username]/bentopdf` + +If/when you merge changes from the source BentoPDF repository, the build and deploy action will automatically be kicked off and the new version will be automatically deployed to GitHub Pages. \ No newline at end of file diff --git a/TRANSLATION.md b/TRANSLATION.md index 00354a5..bfb3d46 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -21,12 +21,30 @@ BentoPDF uses **i18next** for internationalization (i18n). Currently supported l - **English** (`en`) - Default - **German** (`de`) +- **Spanish** (`es`) +- **French** (`fr`) +- **Italian** (`it`) +- **Portuguese** (`pt`) +- **Turkish** (`tr`) - **Vietnamese** (`vi`) +- **Indonesian** (`id`) +- **Chinese** (`zh`) +- **Traditional Chinese (Taiwan)** (`zh-TW`) The app automatically detects the language from the URL path: -- `/en/` → English + +- `/` or `/en/` → English (default) - `/de/` → German -- `/vi/` → Vietnamese +- `/fr/` → French +- etc. + +### Architecture + +BentoPDF uses a **static pre-rendering** approach for SEO-optimized i18n: + +1. **Build time**: `scripts/generate-i18n-pages.mjs` generates localized HTML files in `dist/{lang}/` +2. **Dev/Preview**: `languageRouterPlugin` in `vite.config.ts` handles URL rewriting +3. **Production**: Nginx serves static files directly from language directories --- @@ -34,50 +52,52 @@ The app automatically detects the language from the URL path: **To improve existing translations:** -1. Navigate to `public/locales/{language}/common.json` +1. Navigate to `public/locales/{language}/common.json` and `public/locales/{language}/tools.json` 2. Find the key you want to update 3. Change the translation value 4. Save and test -**To add a new language (e.g., Spanish):** +**To add a new language (e.g., Japanese `ja`):** -1. Copy `public/locales/en/common.json` to `public/locales/es/common.json` -2. Translate all values in `es/common.json` -3. Add Spanish to `supportedLanguages` in `src/js/i18n/i18n.ts` -4. Add Spanish name to `languageNames` in `src/js/i18n/i18n.ts` -5. Test thoroughly +1. Copy `public/locales/en/` to `public/locales/ja/` +2. Translate all values in both `ja/common.json` and `ja/tools.json` +3. Add Japanese to `supportedLanguages` and `languageNames` in `src/js/i18n/i18n.ts` +4. Add `'ja'` to `SUPPORTED_LANGUAGES` in `vite.config.ts` +5. Restart the dev server +6. Run `npm run build` to generate static language pages +7. Test thoroughly --- ## Adding a New Language -Let's add **French** as an example: +Let's add **Spanish** as an example: -### Step 1: Create Translation File +### Step 1: Create Translation Files ```bash # Create the directory -mkdir -p public/locales/fr +mkdir -p public/locales/es # Copy the English template -cp public/locales/en/common.json public/locales/fr/common.json +cp public/locales/en/common.json public/locales/es/common.json ``` -### Step 2: Translate the JSON File +### Step 2: Translate the JSON Files -Open `public/locales/fr/common.json` and translate all the values: +Open `public/locales/es/common.json` and translate all the values: ```json { "nav": { - "home": "Accueil", - "about": "À propos", - "contact": "Contact", - "allTools": "Tous les outils" + "home": "Inicio", + "about": "Acerca de", + "contact": "Contacto", + "allTools": "Todas las herramientas" }, "hero": { - "title": "Votre boîte à outils PDF gratuite et sécurisée", - "subtitle": "Fusionnez, divisez, compressez et modifiez des PDF directement dans votre navigateur." + "title": "Tu conjunto de herramientas PDF gratuito y seguro", + "subtitle": "Combina, divide, comprime y edita archivos PDF directamente en tu navegador." } // ... continue translating all keys } @@ -86,40 +106,78 @@ Open `public/locales/fr/common.json` and translate all the values: ⚠️ **Important**: Only translate the **values**, NOT the keys! ✅ **Correct:** + ```json -"home": "Accueil" +"home": "Inicio" ``` ❌ **Wrong:** + ```json -"accueil": "Accueil" +"inicio": "Inicio" ``` +Then do the same for `public/locales/fr/tools.json` to translate all tool names and descriptions. + ### Step 3: Register the Language Edit `src/js/i18n/i18n.ts`: ```typescript // Add 'fr' to supported languages -export const supportedLanguages = ['en', 'de', 'fr'] as const; +export const supportedLanguages = ['en', 'de', 'es', 'fr', 'zh', 'vi'] as const; export type SupportedLanguage = (typeof supportedLanguages)[number]; // Add French display name export const languageNames: Record = { - en: 'English', - de: 'Deutsch', - fr: 'Français', // ← Add this + en: 'English', + de: 'Deutsch', + fr: 'Français', // ← Add this }; ``` -### Step 4: Test Your Translation +### Step 4: Update Vite Configuration + +In `vite.config.ts`, add your language to the `SUPPORTED_LANGUAGES` array: + +```typescript +const SUPPORTED_LANGUAGES = [ + 'en', + 'de', + 'es', + 'zh', + 'zh-TW', + 'vi', + 'it', + 'id', + 'tr', + 'fr', + 'pt', + 'ja', +] as const; +``` + +> **Important**: This is required for both dev server routing and the build-time i18n generation. + +### Step 5: Test Your Translation ```bash -# Start the dev server +# Restart the dev server npm run dev -# Visit the French version -# http://localhost:5173/fr/ +# Visit the Japanese version +# http://localhost:5173/ja/ +``` + +### Step 6: Build and Verify Static Files + +```bash +# Run build (includes i18n page generation) +npm run build + +# Verify files were created +ls dist/ja/ +# Should show: index.html, merge-pdf.html, etc. ``` --- @@ -207,6 +265,7 @@ Tool names and descriptions are defined in `src/js/config/tools.ts` and use a sp ``` In translations: + ```json { "tools": { @@ -234,14 +293,15 @@ console.log(message); // "Error" or "Fehler" depending on language For input placeholders: ```html - ``` In `common.json`: + ```json { "tools": { @@ -257,6 +317,7 @@ In `common.json`: ### Manual Testing 1. **Start development server:** + ```bash npm run dev ``` @@ -265,7 +326,11 @@ In `common.json`: - English: `http://localhost:5173/en/` - German: `http://localhost:5173/de/` - Vietnamese: `http://localhost:5173/vi/` - - Your new language: `http://localhost:5173/fr/` + - Indonesian: `http://localhost:5173/id/` + - Chinese: `http://localhost:5173/zh/` + - Traditional Chinese (Taiwan): `http://localhost:5173/zh-TW/` + - French: `http://localhost:5173/fr/` + - Your new language: `http://localhost:5173/es/` 3. **Check these pages:** - Homepage (`/`) @@ -289,11 +354,12 @@ Check for missing translations: node scripts/check-translations.js ``` -*(If this script doesn't exist, you may need to create it or manually compare JSON files)* +_(If this script doesn't exist, you may need to create it or manually compare JSON files)_ ### Browser Testing Test in different browsers: + - Chrome/Edge - Firefox - Safari @@ -307,11 +373,13 @@ Test in different browsers: BentoPDF is **friendly, clear, and professional**. Match this tone in your translations. ✅ **Good:** + ```json "hero.title": "Ihr kostenloses und sicheres PDF-Toolkit" ``` ❌ **Too formal:** + ```json "hero.title": "Ihr gebührenfreies und gesichertes Werkzeug für PDF-Dokumente" ``` @@ -339,6 +407,7 @@ When translating, **keep the HTML tags intact**: If your language has complex plural rules or gender distinctions, consult the [i18next pluralization guide](https://www.i18next.com/translation-function/plurals). Example: + ```json { "pages": "page", @@ -349,6 +418,7 @@ Example: ### 4. Don't Translate Brand Names or Legal Terms Keep these as-is: + - BentoPDF - PDF - GitHub @@ -361,6 +431,7 @@ Keep these as-is: ### 5. Technical Terms For technical terms, use commonly accepted translations in your language: + - "Merge" → "Fusionner" (French), "Zusammenführen" (German) - "Split" → "Diviser" (French), "Teilen" (German) - "Compress" → "Compresser" (French), "Komprimieren" (German) @@ -380,6 +451,7 @@ If a translation is much longer, test it visually to ensure it doesn't break the ### Issue: Translations Not Showing Up **Solution:** + 1. Clear your browser cache 2. Hard refresh (Ctrl+F5 or Cmd+Shift+R) 3. Check browser console for errors @@ -388,22 +460,26 @@ If a translation is much longer, test it visually to ensure it doesn't break the ### Issue: Some Text Still in English **Possible causes:** + 1. Missing translation key in your language file 2. Missing `data-i18n` attribute in HTML 3. Hardcoded text in JavaScript **Solution:** + - Compare your language file with `en/common.json` to find missing keys - Search the codebase for hardcoded strings ### Issue: JSON Syntax Error **Symptoms:** + ``` SyntaxError: Unexpected token } in JSON at position 1234 ``` **Solution:** + - Use a JSON validator: https://jsonlint.com/ - Common mistakes: - Trailing comma after last item @@ -414,15 +490,50 @@ SyntaxError: Unexpected token } in JSON at position 1234 **Solution:** Make sure you added the language to both arrays in `i18n.ts`: + ```typescript -export const supportedLanguages = ['en', 'de', 'fr']; // ← Add here +export const supportedLanguages = ['en', 'de', 'es', 'fr', 'zh', 'vi']; // ← Add here export const languageNames = { - en: 'English', - de: 'Deutsch', - fr: 'Français', // ← And here + en: 'English', + de: 'Deutsch', + es: 'Español', + fr: 'Français', // ← And here + zh: '中文', + vi: 'Tiếng Việt', }; ``` +### Issue: 404 Error When Accessing Language Pages + +**Symptoms:** +Visiting `http://localhost:5173/ja/about.html` shows a 404 error page. + +**Solution:** +You need to add your language code to `SUPPORTED_LANGUAGES` in `vite.config.ts`: + +```typescript +const SUPPORTED_LANGUAGES = [ + 'en', + 'de', + 'es', + 'zh', + 'zh-TW', + 'vi', + 'it', + 'id', + 'tr', + 'fr', + 'pt', + 'ja', +] as const; +``` + +After updating, restart the dev server: + +```bash +npm run dev +``` + --- ## File Checklist @@ -430,11 +541,15 @@ export const languageNames = { When adding a new language, make sure these files are updated: - [ ] `public/locales/{lang}/common.json` - Main translation file +- [ ] `public/locales/{lang}/tools.json` - Tools translation file - [ ] `src/js/i18n/i18n.ts` - Add to `supportedLanguages` and `languageNames` +- [ ] `vite.config.ts` - Add to `SUPPORTED_LANGUAGES` array - [ ] Test all pages: homepage, about, contact, FAQ, tool pages - [ ] Test settings modal and shortcuts - [ ] Test language switcher in footer - [ ] Verify URL routing works (`/{lang}/`) +- [ ] Run `npm run build` and verify `dist/{lang}/` folder is created +- [ ] Test that all tools load correctly --- @@ -470,13 +585,21 @@ Thank you for contributing to BentoPDF! 🎉 Current translation coverage: -| Language | Code | Status | Maintainer | -|----------|------|--------|------------| -| English | `en` | ✅ Complete | Core team | -| German | `de` | 🚧 In Progress | Core team | -| Vietnamese | `vi` | ✅ Complete | Community | -| Your Language | `??` | 🚧 In Progress | You? | +| Language | Code | Status | Maintainer | +| ------------------- | ------- | -------------- | ---------- | +| English | `en` | ✅ Complete | Core team | +| German | `de` | ✅ Complete | Community | +| Spanish | `es` | ✅ Complete | Community | +| French | `fr` | ✅ Complete | Community | +| Italian | `it` | ✅ Complete | Community | +| Portuguese | `pt` | ✅ Complete | Community | +| Turkish | `tr` | ✅ Complete | Community | +| Vietnamese | `vi` | ✅ Complete | Community | +| Indonesian | `id` | ✅ Complete | Community | +| Chinese | `zh` | ✅ Complete | Community | +| Traditional Chinese | `zh-TW` | ✅ Complete | Community | +| Your Language | `??` | 🚧 In Progress | You? | --- -**Last Updated**: December 2025 +**Last Updated**: January 2026 diff --git a/about.html b/about.html index 42bb2c6..76dd16b 100644 --- a/about.html +++ b/about.html @@ -1,290 +1,315 @@ + + + - - - - About Bentopdf - Fast, Private, and Free PDF Tools - - - - - - - - - - + + About BentoPDF - Privacy-First Free PDF Tools | Our Mission + + + + - - + -
-
-

- We believe PDF tools should be - fast, private, and free. -

-

No compromises.

-
+ + -
+ + + + + + + -
-
- -

- Our Mission -

-

- To provide the most comprehensive PDF toolbox that respects your - privacy and never asks for payment. We believe essential document - tools should be accessible to everyone, everywhere, without - barriers. + + {{> navbar }} + +

+
+

+ We believe PDF tools should be + fast, private, and free. +

+

+ No compromises.

-
-
+ -
-
-
- Our Core - Philosophy -

- Privacy First. Always. +
+ +
+
+ +

+ Our Mission

-

- In an era where data is a commodity, we take a different approach. - All processing for Bentopdf tools happens locally in your browser. - This means your files never touch our servers, we never see your - documents, and we don't track what you do. Your documents remain - completely and unequivocally private. It's not just a feature; - it's our foundation. +

+ To provide the most comprehensive PDF toolbox that respects your + privacy and never asks for payment. We believe essential document + tools should be accessible to everyone, everywhere, without + barriers.

-
-
-
-
- +
+ +
+
+
+ Our Core Philosophy +

+ Privacy First. Always. +

+

+ In an era where data is a commodity, we take a different approach. + All processing for Bentopdf tools happens locally in your browser. + This means your files never touch our servers, we never see your + documents, and we don't track what you do. Your documents remain + completely and unequivocally private. It's not just a feature; + it's our foundation. +

+
+
+
+
+
+ +
+ +
+

+ Why + Bentopdf? +

+
+
+ +
+

+ Built for Speed +

+

+ No waiting for uploads or downloads to a server. By processing + files directly in your browser using modern web technologies + like WebAssembly, we offer unparalleled speed for all our tools. +

+
+
+
+ +
+

+ Completely Free +

+

+ No trials, no subscriptions, no hidden fees, and no "premium" + features held hostage. We believe powerful PDF tools should be a + public utility, not a profit center. +

+
+
+
+ +
+

+ No Account Required +

+

+ Start using any tool immediately. We don't need your email, a + password, or any personal information. Your workflow should be + frictionless and anonymous. +

+
+
+
+ +
+

+ Open Source Spirit +

+

+ Built with transparency in mind. We leverage incredible + open-source libraries like PDF-lib and PDF.js, and believe in + the community-driven effort to make powerful tools accessible to + everyone. +

+
+
+
+
+ +
+ +
+

+ Ready to get started? +

+

+ Join thousands of users who trust Bentopdf for their daily document + needs. Experience the difference that privacy and performance can + make. +

+ + Explore All Tools + +

-
-

- Why Bentopdf? -

-
-
- -
-

Built for Speed

-

- No waiting for uploads or downloads to a server. By processing - files directly in your browser using modern web technologies - like WebAssembly, we offer unparalleled speed for all our tools. -

-
-
-
- -
-

Completely Free

-

- No trials, no subscriptions, no hidden fees, and no "premium" - features held hostage. We believe powerful PDF tools should be a - public utility, not a profit center. -

-
-
-
- -
-

No Account Required -

-

- Start using any tool immediately. We don't need your email, a - password, or any personal information. Your workflow should be - frictionless and anonymous. -

-
-
-
- -
-

Open Source Spirit -

-

- Built with transparency in mind. We leverage incredible - open-source libraries like PDF-lib and PDF.js, and believe in - the community-driven effort to make powerful tools accessible to - everyone. -

-
-
-
-
+ {{> footer }} -
+ + + + -
-

- Ready to get started? -

-

- Join thousands of users who trust Bentopdf for their daily document - needs. Experience the difference that privacy and performance can - make. -

- - Explore All Tools - -
-
- - - - - - - - - - \ No newline at end of file + + + + diff --git a/chart/.helmignore b/chart/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/chart/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/chart/Chart.yaml b/chart/Chart.yaml new file mode 100644 index 0000000..812fd93 --- /dev/null +++ b/chart/Chart.yaml @@ -0,0 +1,16 @@ +apiVersion: v2 +name: bentopdf +description: BentoPDF static frontend served by NGINX +icon: https://raw.githubusercontent.com/spwoodcock/bentopdf/refs/heads/main/public/favicon.ico +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.2.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.15.4" diff --git a/chart/README.md b/chart/README.md new file mode 100644 index 0000000..5199ab9 --- /dev/null +++ b/chart/README.md @@ -0,0 +1,114 @@ +# BentoPDF Helm Chart + +Deploys **BentoPDF** as a **single NGINX container** serving the static frontend. + +## Prereqs + +- Kubernetes cluster +- Helm v3 with OCI support +- An image that serves BentoPDF via nginx (default chart expects the repo image, which listens on **8080** inside the container) + +## Quickstart (ClusterIP + port-forward) + +```bash +helm install bentopdf ./chart + +kubectl port-forward deploy/bentopdf 8080:8080 +# open http://127.0.0.1:8080 +``` + +## Configuration + +### Image + +- **`image.repository`**: container image repo (default `bentopdf/bentopdf`) +- **`image.tag`**: image tag (default: `Chart.appVersion`) +- **`image.pullPolicy`**: default `IfNotPresent` + +### Ports + +- **`containerPort`**: container listen port (**8080** for the BentoPDF nginx image) +- **`service.port`**: Service port exposed in-cluster (default **80**) + +### Environment variables + +Use **`env`** for the container. + +Example (IPv4-only environments): + +```yaml +env: + - name: DISABLE_IPV6 + value: "true" +``` + +### Ingress (optional) + +Enable the built-in Kubernetes Ingress: + +```yaml +ingress: + enabled: true + className: nginx + hosts: + - host: bentopdf.example.com + paths: + - path: / + pathType: Prefix +``` + +### Gateway API: Gateway + HTTPRoute (optional) + +This chart can optionally: + +- Create a **Gateway** (`gateway.enabled=true`) +- Create an **HTTPRoute** (`httpRoute.enabled=true`) that points at the chart Service + +If your cluster uses a shared Gateway created elsewhere, set `gateway.enabled=false` and point `httpRoute.parentRefs` to that Gateway. + +Example (create both Gateway + HTTPRoute): + +```yaml +gateway: + enabled: true + gatewayClassName: cloudflare # or nginx, istio, etc (controller-specific) + listeners: + - name: http + protocol: HTTP + port: 80 + +httpRoute: + enabled: true + hostnames: + - bentopdf.example.com + parentRefs: + - name: "" # default: release fullname (or gateway.name if set) + sectionName: http + rules: + - matches: + - path: + type: PathPrefix + value: / +``` + +## Publish this chart to GHCR (OCI) for testing/deploying + +### Build And Push OCI + +```bash +echo "$GHCR_TOKEN" | helm registry login ghcr.io -u "$GHCR_USERNAME" --password-stdin + +cd chart +helm package . + +# produces bentopdf-.tgz +helm push bentopdf-*.tgz oci://ghcr.io/$GHCR_USERNAME/charts +``` + +This could be automated as part of a Github workflow. + +### Deploy + +```bash +helm upgrade --install bentopdf oci://ghcr.io/$GHCR_USERNAME/charts/bentopdf --version 0.1.0 +``` diff --git a/chart/templates/NOTES.txt b/chart/templates/NOTES.txt new file mode 100644 index 0000000..137f4f1 --- /dev/null +++ b/chart/templates/NOTES.txt @@ -0,0 +1,35 @@ +1. Get the application URL by running these commands: +{{- if .Values.httpRoute.enabled }} +{{- if .Values.httpRoute.hostnames }} + export APP_HOSTNAME={{ .Values.httpRoute.hostnames | first }} +{{- else }} + export APP_HOSTNAME=$(kubectl get --namespace {{(first .Values.httpRoute.parentRefs).namespace | default .Release.Namespace }} gateway/{{ (first .Values.httpRoute.parentRefs).name }} -o jsonpath="{.spec.listeners[0].hostname}") + {{- end }} +{{- if and .Values.httpRoute.rules (first .Values.httpRoute.rules).matches (first (first .Values.httpRoute.rules).matches).path.value }} + echo "Visit http://$APP_HOSTNAME{{ (first (first .Values.httpRoute.rules).matches).path.value }} to use your application" + + NOTE: Your HTTPRoute depends on the listener configuration of your gateway and your HTTPRoute rules. + The rules can be set for path, method, header and query parameters. + You can check the gateway configuration with 'kubectl get --namespace {{(first .Values.httpRoute.parentRefs).namespace | default .Release.Namespace }} gateway/{{ (first .Values.httpRoute.parentRefs).name }} -o yaml' +{{- end }} +{{- else if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "chart.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch its status by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "chart.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "chart.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "chart.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl new file mode 100644 index 0000000..52b41f3 --- /dev/null +++ b/chart/templates/_helpers.tpl @@ -0,0 +1,52 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "chart.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "chart.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "chart.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "chart.labels" -}} +helm.sh/chart: {{ include "chart.chart" . }} +{{ include "chart.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "chart.selectorLabels" -}} +app.kubernetes.io/name: {{ include "chart.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml new file mode 100644 index 0000000..5cde309 --- /dev/null +++ b/chart/templates/deployment.yaml @@ -0,0 +1,51 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "chart.fullname" . }} + labels: + {{- include "chart.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "chart.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "chart.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.containerPort }} + protocol: TCP + {{- with .Values.env }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} diff --git a/chart/templates/gateway.yaml b/chart/templates/gateway.yaml new file mode 100644 index 0000000..b43028f --- /dev/null +++ b/chart/templates/gateway.yaml @@ -0,0 +1,17 @@ +{{- if .Values.gateway.enabled -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: {{ default (include "chart.fullname" .) .Values.gateway.name }} + namespace: {{ default .Release.Namespace .Values.gateway.namespace }} + labels: + {{- include "chart.labels" . | nindent 4 }} + {{- with .Values.gateway.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + gatewayClassName: {{ required "values.gateway.gatewayClassName is required when gateway.enabled=true" .Values.gateway.gatewayClassName }} + listeners: + {{- toYaml .Values.gateway.listeners | nindent 4 }} +{{- end }} diff --git a/chart/templates/httproute.yaml b/chart/templates/httproute.yaml new file mode 100644 index 0000000..38a527a --- /dev/null +++ b/chart/templates/httproute.yaml @@ -0,0 +1,51 @@ +{{- if .Values.httpRoute.enabled -}} +{{- $fullName := include "chart.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- $defaultGatewayName := (default $fullName .Values.gateway.name) -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ $fullName }} + labels: + {{- include "chart.labels" . | nindent 4 }} + {{- with .Values.httpRoute.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + parentRefs: + {{- range $ref := .Values.httpRoute.parentRefs }} + - name: {{ default $defaultGatewayName $ref.name | quote }} + {{- with $ref.sectionName }} + sectionName: {{ . | quote }} + {{- end }} + {{- with $ref.namespace }} + namespace: {{ . | quote }} + {{- end }} + {{- with $ref.kind }} + kind: {{ . | quote }} + {{- end }} + {{- with $ref.group }} + group: {{ . | quote }} + {{- end }} + {{- end }} + {{- with .Values.httpRoute.hostnames }} + hostnames: + {{- toYaml . | nindent 4 }} + {{- end }} + rules: + {{- range .Values.httpRoute.rules }} + {{- with .matches }} + - matches: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .filters }} + filters: + {{- toYaml . | nindent 8 }} + {{- end }} + backendRefs: + - name: {{ $fullName }} + port: {{ $svcPort }} + weight: 1 + {{- end }} +{{- end }} diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml new file mode 100644 index 0000000..89ec883 --- /dev/null +++ b/chart/templates/ingress.yaml @@ -0,0 +1,43 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "chart.fullname" . }} + labels: + {{- include "chart.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.ingress.className }} + ingressClassName: {{ . }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- with .pathType }} + pathType: {{ . }} + {{- end }} + backend: + service: + name: {{ include "chart.fullname" $ }} + port: + number: {{ $.Values.service.port }} + {{- end }} + {{- end }} +{{- end }} diff --git a/chart/templates/service.yaml b/chart/templates/service.yaml new file mode 100644 index 0000000..dfc5b3a --- /dev/null +++ b/chart/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "chart.fullname" . }} + labels: + {{- include "chart.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "chart.selectorLabels" . | nindent 4 }} diff --git a/chart/templates/serviceaccount.yaml b/chart/templates/serviceaccount.yaml new file mode 100644 index 0000000..ff2b900 --- /dev/null +++ b/chart/templates/serviceaccount.yaml @@ -0,0 +1,4 @@ +# The service account was removed, as it's not necessary for a chart like this. +# +# There are no calls to the Kubernetes API - routing between services. +# It's a simple nginx static website deployment only. diff --git a/chart/templates/tests/test-connection.yaml b/chart/templates/tests/test-connection.yaml new file mode 100644 index 0000000..2a38998 --- /dev/null +++ b/chart/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "chart.fullname" . }}-test-connection" + labels: + {{- include "chart.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['-qO-', 'http://{{ include "chart.fullname" . }}:{{ .Values.service.port }}/'] + restartPolicy: Never diff --git a/chart/values.yaml b/chart/values.yaml new file mode 100644 index 0000000..6670d22 --- /dev/null +++ b/chart/values.yaml @@ -0,0 +1,72 @@ +# Default values for the BentoPDF chart (single nginx static frontend). +replicaCount: 1 + +image: + # Image built from this repo's `Dockerfile` (nginx serving static frontend). + repository: alam00000/bentopdf-simple + pullPolicy: IfNotPresent + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +podAnnotations: {} +podLabels: {} + +service: + type: ClusterIP + port: 80 + +# Container listen port (BentoPDF nginx image listens on 8080). +containerPort: 8080 + +env: [] + +ingress: + enabled: false + className: "" + annotations: {} + hosts: + - host: bentopdf.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + +# Gateway API (optional) +gateway: + enabled: false + name: "" # default: release fullname + namespace: "" # default: release namespace + annotations: {} + gatewayClassName: "" # required when enabled=true + listeners: + - name: http + protocol: HTTP + port: 80 + +httpRoute: + enabled: false + annotations: {} + parentRefs: + - name: "" # default: gateway.name (if set) else release fullname + sectionName: http + hostnames: + - bentopdf.local + rules: + - matches: + - path: + type: PathPrefix + value: / + +resources: {} + +livenessProbe: + httpGet: + path: / + port: http +readinessProbe: + httpGet: + path: / + port: http diff --git a/cloudflare/cors-proxy-worker.js b/cloudflare/cors-proxy-worker.js new file mode 100644 index 0000000..b9ba458 --- /dev/null +++ b/cloudflare/cors-proxy-worker.js @@ -0,0 +1,351 @@ +/** + * BentoPDF CORS Proxy Worker + * + * This Cloudflare Worker proxies certificate requests for the digital signing tool. + * It fetches certificates from external CAs that don't have CORS headers enabled + * and returns them with proper CORS headers. + * + * + * Deploy: npx wrangler deploy + * + * Required Environment Variables (set in wrangler.toml or Cloudflare dashboard): + * - PROXY_SECRET: Shared secret for HMAC signature verification + */ + +const ALLOWED_PATTERNS = [ + /\.crt$/i, + /\.cer$/i, + /\.pem$/i, + /\/certs\//i, + /\/ocsp/i, + /\/crl/i, + /caIssuers/i, +]; + +const ALLOWED_ORIGINS = [ + 'https://www.bentopdf.com', + 'https://bentopdf.com', +]; + +const BLOCKED_DOMAINS = [ + 'localhost', + '127.0.0.1', + '0.0.0.0', +]; + + +const MAX_TIMESTAMP_AGE_MS = 5 * 60 * 1000; + +const RATE_LIMIT_MAX_REQUESTS = 60; +const RATE_LIMIT_WINDOW_MS = 60 * 1000; + +const MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024; + +async function verifySignature(message, signature, secret) { + try { + const encoder = new TextEncoder(); + const key = await crypto.subtle.importKey( + 'raw', + encoder.encode(secret), + { name: 'HMAC', hash: 'SHA-256' }, + false, + ['verify'] + ); + + const signatureBytes = new Uint8Array( + signature.match(/.{1,2}/g).map(byte => parseInt(byte, 16)) + ); + + return await crypto.subtle.verify( + 'HMAC', + key, + signatureBytes, + encoder.encode(message) + ); + } catch (e) { + console.error('Signature verification error:', e); + return false; + } +} + +async function generateSignature(message, secret) { + const encoder = new TextEncoder(); + const key = await crypto.subtle.importKey( + 'raw', + encoder.encode(secret), + { name: 'HMAC', hash: 'SHA-256' }, + false, + ['sign'] + ); + + const signature = await crypto.subtle.sign( + 'HMAC', + key, + encoder.encode(message) + ); + + return Array.from(new Uint8Array(signature)) + .map(b => b.toString(16).padStart(2, '0')) + .join(''); +} + +function isAllowedOrigin(origin) { + if (!origin) return false; + return ALLOWED_ORIGINS.some(allowed => origin.startsWith(allowed.replace(/\/$/, ''))); +} + +function isValidCertificateUrl(urlString) { + try { + const url = new URL(urlString); + + if (!['http:', 'https:'].includes(url.protocol)) { + return false; + } + + if (BLOCKED_DOMAINS.some(domain => url.hostname.includes(domain))) { + return false; + } + + const hostname = url.hostname; + if (/^10\./.test(hostname) || + /^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(hostname) || + /^192\.168\./.test(hostname)) { + return false; + } + + return ALLOWED_PATTERNS.some(pattern => pattern.test(urlString)); + } catch { + return false; + } +} + +function corsHeaders(origin) { + return { + 'Access-Control-Allow-Origin': origin || '*', + 'Access-Control-Allow-Methods': 'GET, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type', + 'Access-Control-Max-Age': '86400', + }; +} + +function handleOptions(request) { + const origin = request.headers.get('Origin'); + return new Response(null, { + status: 204, + headers: corsHeaders(origin), + }); +} + +export default { + async fetch(request, env, ctx) { + const url = new URL(request.url); + const origin = request.headers.get('Origin'); + + if (request.method === 'OPTIONS') { + return handleOptions(request); + } + + // NOTE: If you are selfhosting this proxy, you can remove this check, or can set it to only accept requests from your own domain + if (!isAllowedOrigin(origin)) { + return new Response(JSON.stringify({ + error: 'Forbidden', + message: 'This proxy only accepts requests from bentopdf.com', + }), { + status: 403, + headers: { + 'Content-Type': 'application/json', + }, + }); + } + + if (request.method !== 'GET') { + return new Response('Method not allowed', { + status: 405, + headers: corsHeaders(origin), + }); + } + + const targetUrl = url.searchParams.get('url'); + const timestamp = url.searchParams.get('t'); + const signature = url.searchParams.get('sig'); + + if (env.PROXY_SECRET) { + if (!timestamp || !signature) { + return new Response(JSON.stringify({ + error: 'Missing authentication parameters', + message: 'Request must include timestamp (t) and signature (sig) parameters', + }), { + status: 401, + headers: { + ...corsHeaders(origin), + 'Content-Type': 'application/json', + }, + }); + } + + const requestTime = parseInt(timestamp, 10); + const now = Date.now(); + if (isNaN(requestTime) || Math.abs(now - requestTime) > MAX_TIMESTAMP_AGE_MS) { + return new Response(JSON.stringify({ + error: 'Request expired or invalid timestamp', + message: 'Timestamp must be within 5 minutes of current time', + }), { + status: 401, + headers: { + ...corsHeaders(origin), + 'Content-Type': 'application/json', + }, + }); + } + + const message = `${targetUrl}${timestamp}`; + const isValid = await verifySignature(message, signature, env.PROXY_SECRET); + + if (!isValid) { + return new Response(JSON.stringify({ + error: 'Invalid signature', + message: 'Request signature verification failed', + }), { + status: 401, + headers: { + ...corsHeaders(origin), + 'Content-Type': 'application/json', + }, + }); + } + } + + if (!targetUrl) { + return new Response(JSON.stringify({ + error: 'Missing url parameter', + usage: 'GET /?url=', + }), { + status: 400, + headers: { + ...corsHeaders(origin), + 'Content-Type': 'application/json', + }, + }); + } + + if (!isValidCertificateUrl(targetUrl)) { + return new Response(JSON.stringify({ + error: 'Invalid or disallowed URL', + message: 'Only certificate-related URLs are allowed (*.crt, *.cer, *.pem, /certs/, /ocsp, /crl)', + }), { + status: 403, + headers: { + ...corsHeaders(origin), + 'Content-Type': 'application/json', + }, + }); + } + + const clientIP = request.headers.get('CF-Connecting-IP') || 'unknown'; + const rateLimitKey = `ratelimit:${clientIP}`; + const now = Date.now(); + + if (env.RATE_LIMIT_KV) { + const rateLimitData = await env.RATE_LIMIT_KV.get(rateLimitKey, { type: 'json' }); + const requests = rateLimitData?.requests || []; + + const recentRequests = requests.filter(t => now - t < RATE_LIMIT_WINDOW_MS); + + if (recentRequests.length >= RATE_LIMIT_MAX_REQUESTS) { + return new Response(JSON.stringify({ + error: 'Rate limit exceeded', + message: `Maximum ${RATE_LIMIT_MAX_REQUESTS} requests per minute. Please try again later.`, + retryAfter: Math.ceil((recentRequests[0] + RATE_LIMIT_WINDOW_MS - now) / 1000), + }), { + status: 429, + headers: { + ...corsHeaders(origin), + 'Content-Type': 'application/json', + 'Retry-After': Math.ceil((recentRequests[0] + RATE_LIMIT_WINDOW_MS - now) / 1000).toString(), + }, + }); + } + + recentRequests.push(now); + await env.RATE_LIMIT_KV.put(rateLimitKey, JSON.stringify({ requests: recentRequests }), { + expirationTtl: 120, + }); + } + + try { + const response = await fetch(targetUrl, { + headers: { + 'User-Agent': 'BentoPDF-CertProxy/1.0', + }, + }); + + if (!response.ok) { + return new Response(JSON.stringify({ + error: 'Failed to fetch certificate', + status: response.status, + statusText: response.statusText, + }), { + status: response.status, + headers: { + ...corsHeaders(origin), + 'Content-Type': 'application/json', + }, + }); + } + + const contentLength = parseInt(response.headers.get('Content-Length') || '0', 10); + if (contentLength > MAX_FILE_SIZE_BYTES) { + return new Response(JSON.stringify({ + error: 'File too large', + message: `Certificate file exceeds maximum size of ${MAX_FILE_SIZE_BYTES / 1024}KB`, + size: contentLength, + maxSize: MAX_FILE_SIZE_BYTES, + }), { + status: 413, + headers: { + ...corsHeaders(origin), + 'Content-Type': 'application/json', + }, + }); + } + + const certData = await response.arrayBuffer(); + + if (certData.byteLength > MAX_FILE_SIZE_BYTES) { + return new Response(JSON.stringify({ + error: 'File too large', + message: `Certificate file exceeds maximum size of ${MAX_FILE_SIZE_BYTES / 1024}KB`, + size: certData.byteLength, + maxSize: MAX_FILE_SIZE_BYTES, + }), { + status: 413, + headers: { + ...corsHeaders(origin), + 'Content-Type': 'application/json', + }, + }); + } + + return new Response(certData, { + status: 200, + headers: { + ...corsHeaders(origin), + 'Content-Type': response.headers.get('Content-Type') || 'application/x-x509-ca-cert', + 'Content-Length': certData.byteLength.toString(), + 'Cache-Control': 'public, max-age=86400', + }, + }); + } catch (error) { + return new Response(JSON.stringify({ + error: 'Proxy error', + message: error.message, + }), { + status: 500, + headers: { + ...corsHeaders(origin), + 'Content-Type': 'application/json', + }, + }); + } + }, +}; diff --git a/cloudflare/wrangler.toml b/cloudflare/wrangler.toml new file mode 100644 index 0000000..491b4ae --- /dev/null +++ b/cloudflare/wrangler.toml @@ -0,0 +1,45 @@ +name = "bentopdf-cors-proxy" +main = "cors-proxy-worker.js" +compatibility_date = "2024-01-01" + +# Deploy to Cloudflare's global network +# If you are self hosting change the name to your worker name +# Run: npx wrangler deploy + +# ============================================================================= +# SECURITY FEATURES +# ============================================================================= +# +# 1. SIGNATURE VERIFICATION (Optional - for anti-spoofing) +# - Generate secret: openssl rand -hex 32 +# - Set secret: npx wrangler secret put PROXY_SECRET +# - Note: Secret is visible in frontend JS, so provides limited protection +# +# 2. RATE LIMITING (Recommended - requires KV) +# - Create KV namespace: npx wrangler kv namespace create "RATE_LIMIT_KV" +# - Uncomment the kv_namespaces section below with the returned ID +# - Limits: 60 requests per IP per minute +# +# 3. FILE SIZE LIMIT +# - Automatic: Rejects files larger than 1MB +# - Certificates are typically <10KB, so this prevents abuse +# +# 4. URL RESTRICTIONS +# - Only certificate URLs allowed (*.crt, *.cer, *.pem, /certs/, etc.) +# - Blocks private IPs (localhost, 10.x, 192.168.x, 172.16-31.x) + +# ============================================================================= +# KV NAMESPACE FOR RATE LIMITING +# ============================================================================= +[[kv_namespaces]] +binding = "RATE_LIMIT_KV" +id = "b88e030b308941118cd484e3fcb3ae49" + +# Optional: Custom domain routing +# routes = [ +# { pattern = "cors-proxy.bentopdf.com/*", zone_name = "bentopdf.com" } +# ] + +# Optional: Environment variables (for non-secret config) +# [vars] +# ALLOWED_ORIGINS = "https://www.bentopdf.com,https://bentopdf.com" \ No newline at end of file diff --git a/contact.html b/contact.html index 2932254..1e9c012 100644 --- a/contact.html +++ b/contact.html @@ -1,183 +1,130 @@ + + + + + Contact BentoPDF - Get in Touch | Support + + + - - - - Contact Us - BentoPDF - - - - - - - - - - + + - - + {{> footer }} -
-
-

- Get in Touch -

-

- We'd love to hear from you. Whether you have a question, feedback, or - a feature request, please don't hesitate to reach out. -

-
- -
-

- You can reach us directly by email at: - contact@bentopdf.com -

-
-
- - - - - - - - - - \ No newline at end of file + + + + + + + + diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 2dc72bf..1e6b4ab 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -9,3 +9,6 @@ services: ports: - '8080:8080' restart: unless-stopped + # For IPv4-only environments + #environment: + # - DISABLE_IPV6=true diff --git a/docker-compose.yml b/docker-compose.yml index 494eff5..95dbe02 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,16 @@ services: bentopdf: - # simple mode - bentopdf/bentopdf-simple:latest - # default mode - bentopdf/bentopdf:latest - image: bentopdf/bentopdf-simple:latest + # GitHub Container Registry (Recommended) + # simple mode - ghcr.io/alam00000/bentopdf-simple:latest + # default mode - ghcr.io/alam00000/bentopdf:latest + # Docker Hub (Alternative) + # simple mode - bentopdfteam/bentopdf-simple:latest + # default mode - bentopdfteam/bentopdf:latest + image: ghcr.io/alam00000/bentopdf-simple:latest container_name: bentopdf restart: unless-stopped ports: - '8080:8080' + # For IPv4-only environments + #environment: + # - DISABLE_IPV6=true diff --git a/docs/.vitepress/cache/deps/@theme_index.js b/docs/.vitepress/cache/deps/@theme_index.js new file mode 100644 index 0000000..991f721 --- /dev/null +++ b/docs/.vitepress/cache/deps/@theme_index.js @@ -0,0 +1,275 @@ +import { + useMediaQuery +} from "./chunk-2CLQ7TTZ.js"; +import { + computed, + ref, + shallowRef, + watch +} from "./chunk-LE5NDSFD.js"; + +// node_modules/vitepress/dist/client/theme-default/index.js +import "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/fonts.css"; + +// node_modules/vitepress/dist/client/theme-default/without-fonts.js +import "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/vars.css"; +import "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/base.css"; +import "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/icons.css"; +import "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/utils.css"; +import "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/components/custom-block.css"; +import "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code.css"; +import "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/components/vp-code-group.css"; +import "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/components/vp-doc.css"; +import "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/styles/components/vp-sponsor.css"; +import VPBadge from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue"; +import Layout from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/Layout.vue"; +import { default as default2 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPBadge.vue"; +import { default as default3 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPButton.vue"; +import { default as default4 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPDocAsideSponsors.vue"; +import { default as default5 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPFeatures.vue"; +import { default as default6 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPHomeContent.vue"; +import { default as default7 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPHomeFeatures.vue"; +import { default as default8 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPHomeHero.vue"; +import { default as default9 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPHomeSponsors.vue"; +import { default as default10 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPImage.vue"; +import { default as default11 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPLink.vue"; +import { default as default12 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPNavBarSearch.vue"; +import { default as default13 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPSocialLink.vue"; +import { default as default14 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPSocialLinks.vue"; +import { default as default15 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPSponsors.vue"; +import { default as default16 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPTeamMembers.vue"; +import { default as default17 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPTeamPage.vue"; +import { default as default18 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageSection.vue"; +import { default as default19 } from "/Users/abdullahtapadar/Desktop/workspaceforbento/bento-pdf/node_modules/vitepress/dist/client/theme-default/components/VPTeamPageTitle.vue"; + +// node_modules/vitepress/dist/client/theme-default/composables/local-nav.js +import { onContentUpdated } from "vitepress"; + +// node_modules/vitepress/dist/client/theme-default/composables/outline.js +import { getScrollOffset } from "vitepress"; + +// node_modules/vitepress/dist/client/theme-default/support/utils.js +import { withBase } from "vitepress"; + +// node_modules/vitepress/dist/client/theme-default/composables/data.js +import { useData as useData$ } from "vitepress"; +var useData = useData$; + +// node_modules/vitepress/dist/client/theme-default/support/utils.js +function ensureStartingSlash(path) { + return path.startsWith("/") ? path : `/${path}`; +} + +// node_modules/vitepress/dist/client/theme-default/support/sidebar.js +function getSidebar(_sidebar, path) { + if (Array.isArray(_sidebar)) + return addBase(_sidebar); + if (_sidebar == null) + return []; + path = ensureStartingSlash(path); + const dir = Object.keys(_sidebar).sort((a, b) => { + return b.split("/").length - a.split("/").length; + }).find((dir2) => { + return path.startsWith(ensureStartingSlash(dir2)); + }); + const sidebar = dir ? _sidebar[dir] : []; + return Array.isArray(sidebar) ? addBase(sidebar) : addBase(sidebar.items, sidebar.base); +} +function getSidebarGroups(sidebar) { + const groups = []; + let lastGroupIndex = 0; + for (const index in sidebar) { + const item = sidebar[index]; + if (item.items) { + lastGroupIndex = groups.push(item); + continue; + } + if (!groups[lastGroupIndex]) { + groups.push({ items: [] }); + } + groups[lastGroupIndex].items.push(item); + } + return groups; +} +function addBase(items, _base) { + return [...items].map((_item) => { + const item = { ..._item }; + const base = item.base || _base; + if (base && item.link) + item.link = base + item.link; + if (item.items) + item.items = addBase(item.items, base); + return item; + }); +} + +// node_modules/vitepress/dist/client/theme-default/composables/sidebar.js +function useSidebar() { + const { frontmatter, page, theme: theme2 } = useData(); + const is960 = useMediaQuery("(min-width: 960px)"); + const isOpen = ref(false); + const _sidebar = computed(() => { + const sidebarConfig = theme2.value.sidebar; + const relativePath = page.value.relativePath; + return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : []; + }); + const sidebar = ref(_sidebar.value); + watch(_sidebar, (next, prev) => { + if (JSON.stringify(next) !== JSON.stringify(prev)) + sidebar.value = _sidebar.value; + }); + const hasSidebar = computed(() => { + return frontmatter.value.sidebar !== false && sidebar.value.length > 0 && frontmatter.value.layout !== "home"; + }); + const leftAside = computed(() => { + if (hasAside) + return frontmatter.value.aside == null ? theme2.value.aside === "left" : frontmatter.value.aside === "left"; + return false; + }); + const hasAside = computed(() => { + if (frontmatter.value.layout === "home") + return false; + if (frontmatter.value.aside != null) + return !!frontmatter.value.aside; + return theme2.value.aside !== false; + }); + const isSidebarEnabled = computed(() => hasSidebar.value && is960.value); + const sidebarGroups = computed(() => { + return hasSidebar.value ? getSidebarGroups(sidebar.value) : []; + }); + function open() { + isOpen.value = true; + } + function close() { + isOpen.value = false; + } + function toggle() { + isOpen.value ? close() : open(); + } + return { + isOpen, + sidebar, + sidebarGroups, + hasSidebar, + hasAside, + leftAside, + isSidebarEnabled, + open, + close, + toggle + }; +} + +// node_modules/vitepress/dist/client/theme-default/composables/outline.js +var ignoreRE = /\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/; +var resolvedHeaders = []; +function getHeaders(range) { + const headers = [ + ...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)") + ].filter((el) => el.id && el.hasChildNodes()).map((el) => { + const level = Number(el.tagName[1]); + return { + element: el, + title: serializeHeader(el), + link: "#" + el.id, + level + }; + }); + return resolveHeaders(headers, range); +} +function serializeHeader(h) { + let ret = ""; + for (const node of h.childNodes) { + if (node.nodeType === 1) { + if (ignoreRE.test(node.className)) + continue; + ret += node.textContent; + } else if (node.nodeType === 3) { + ret += node.textContent; + } + } + return ret.trim(); +} +function resolveHeaders(headers, range) { + if (range === false) { + return []; + } + const levelsRange = (typeof range === "object" && !Array.isArray(range) ? range.level : range) || 2; + const [high, low] = typeof levelsRange === "number" ? [levelsRange, levelsRange] : levelsRange === "deep" ? [2, 6] : levelsRange; + return buildTree(headers, high, low); +} +function buildTree(data, min, max) { + resolvedHeaders.length = 0; + const result = []; + const stack = []; + data.forEach((item) => { + const node = { ...item, children: [] }; + let parent = stack[stack.length - 1]; + while (parent && parent.level >= node.level) { + stack.pop(); + parent = stack[stack.length - 1]; + } + if (node.element.classList.contains("ignore-header") || parent && "shouldIgnore" in parent) { + stack.push({ level: node.level, shouldIgnore: true }); + return; + } + if (node.level > max || node.level < min) + return; + resolvedHeaders.push({ element: node.element, link: node.link }); + if (parent) + parent.children.push(node); + else + result.push(node); + stack.push(node); + }); + return result; +} + +// node_modules/vitepress/dist/client/theme-default/composables/local-nav.js +function useLocalNav() { + const { theme: theme2, frontmatter } = useData(); + const headers = shallowRef([]); + const hasLocalNav = computed(() => { + return headers.value.length > 0; + }); + onContentUpdated(() => { + headers.value = getHeaders(frontmatter.value.outline ?? theme2.value.outline); + }); + return { + headers, + hasLocalNav + }; +} + +// node_modules/vitepress/dist/client/theme-default/without-fonts.js +var theme = { + Layout, + enhanceApp: ({ app }) => { + app.component("Badge", VPBadge); + } +}; +var without_fonts_default = theme; +export { + default2 as VPBadge, + default3 as VPButton, + default4 as VPDocAsideSponsors, + default5 as VPFeatures, + default6 as VPHomeContent, + default7 as VPHomeFeatures, + default8 as VPHomeHero, + default9 as VPHomeSponsors, + default10 as VPImage, + default11 as VPLink, + default12 as VPNavBarSearch, + default13 as VPSocialLink, + default14 as VPSocialLinks, + default15 as VPSponsors, + default16 as VPTeamMembers, + default17 as VPTeamPage, + default18 as VPTeamPageSection, + default19 as VPTeamPageTitle, + without_fonts_default as default, + useLocalNav, + useSidebar +}; +//# sourceMappingURL=@theme_index.js.map diff --git a/docs/.vitepress/cache/deps/@theme_index.js.map b/docs/.vitepress/cache/deps/@theme_index.js.map new file mode 100644 index 0000000..76de7c1 --- /dev/null +++ b/docs/.vitepress/cache/deps/@theme_index.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../../../../node_modules/vitepress/dist/client/theme-default/index.js", "../../../../node_modules/vitepress/dist/client/theme-default/without-fonts.js", "../../../../node_modules/vitepress/dist/client/theme-default/composables/local-nav.js", "../../../../node_modules/vitepress/dist/client/theme-default/composables/outline.js", "../../../../node_modules/vitepress/dist/client/theme-default/support/utils.js", "../../../../node_modules/vitepress/dist/client/theme-default/composables/data.js", "../../../../node_modules/vitepress/dist/client/theme-default/support/sidebar.js", "../../../../node_modules/vitepress/dist/client/theme-default/composables/sidebar.js"], + "sourcesContent": ["import './styles/fonts.css';\nexport * from './without-fonts';\nexport { default as default } from './without-fonts';\n", "import './styles/vars.css';\nimport './styles/base.css';\nimport './styles/icons.css';\nimport './styles/utils.css';\nimport './styles/components/custom-block.css';\nimport './styles/components/vp-code.css';\nimport './styles/components/vp-code-group.css';\nimport './styles/components/vp-doc.css';\nimport './styles/components/vp-sponsor.css';\nimport VPBadge from './components/VPBadge.vue';\nimport Layout from './Layout.vue';\nexport { default as VPBadge } from './components/VPBadge.vue';\nexport { default as VPButton } from './components/VPButton.vue';\nexport { default as VPDocAsideSponsors } from './components/VPDocAsideSponsors.vue';\nexport { default as VPFeatures } from './components/VPFeatures.vue';\nexport { default as VPHomeContent } from './components/VPHomeContent.vue';\nexport { default as VPHomeFeatures } from './components/VPHomeFeatures.vue';\nexport { default as VPHomeHero } from './components/VPHomeHero.vue';\nexport { default as VPHomeSponsors } from './components/VPHomeSponsors.vue';\nexport { default as VPImage } from './components/VPImage.vue';\nexport { default as VPLink } from './components/VPLink.vue';\nexport { default as VPNavBarSearch } from './components/VPNavBarSearch.vue';\nexport { default as VPSocialLink } from './components/VPSocialLink.vue';\nexport { default as VPSocialLinks } from './components/VPSocialLinks.vue';\nexport { default as VPSponsors } from './components/VPSponsors.vue';\nexport { default as VPTeamMembers } from './components/VPTeamMembers.vue';\nexport { default as VPTeamPage } from './components/VPTeamPage.vue';\nexport { default as VPTeamPageSection } from './components/VPTeamPageSection.vue';\nexport { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue';\nexport { useLocalNav } from './composables/local-nav';\nexport { useSidebar } from './composables/sidebar';\nconst theme = {\n Layout,\n enhanceApp: ({ app }) => {\n app.component('Badge', VPBadge);\n }\n};\nexport default theme;\n", "import { onContentUpdated } from 'vitepress';\nimport { computed, shallowRef } from 'vue';\nimport { getHeaders } from '../composables/outline';\nimport { useData } from './data';\nexport function useLocalNav() {\n const { theme, frontmatter } = useData();\n const headers = shallowRef([]);\n const hasLocalNav = computed(() => {\n return headers.value.length > 0;\n });\n onContentUpdated(() => {\n headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline);\n });\n return {\n headers,\n hasLocalNav\n };\n}\n", "import { getScrollOffset } from 'vitepress';\nimport { onMounted, onUnmounted, onUpdated } from 'vue';\nimport { throttleAndDebounce } from '../support/utils';\nimport { useAside } from './aside';\nconst ignoreRE = /\\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\\b/;\n// cached list of anchor elements from resolveHeaders\nconst resolvedHeaders = [];\nexport function resolveTitle(theme) {\n return ((typeof theme.outline === 'object' &&\n !Array.isArray(theme.outline) &&\n theme.outline.label) ||\n theme.outlineTitle ||\n 'On this page');\n}\nexport function getHeaders(range) {\n const headers = [\n ...document.querySelectorAll('.VPDoc :where(h1,h2,h3,h4,h5,h6)')\n ]\n .filter((el) => el.id && el.hasChildNodes())\n .map((el) => {\n const level = Number(el.tagName[1]);\n return {\n element: el,\n title: serializeHeader(el),\n link: '#' + el.id,\n level\n };\n });\n return resolveHeaders(headers, range);\n}\nfunction serializeHeader(h) {\n let ret = '';\n for (const node of h.childNodes) {\n if (node.nodeType === 1) {\n if (ignoreRE.test(node.className))\n continue;\n ret += node.textContent;\n }\n else if (node.nodeType === 3) {\n ret += node.textContent;\n }\n }\n return ret.trim();\n}\nexport function resolveHeaders(headers, range) {\n if (range === false) {\n return [];\n }\n const levelsRange = (typeof range === 'object' && !Array.isArray(range)\n ? range.level\n : range) || 2;\n const [high, low] = typeof levelsRange === 'number'\n ? [levelsRange, levelsRange]\n : levelsRange === 'deep'\n ? [2, 6]\n : levelsRange;\n return buildTree(headers, high, low);\n}\nexport function useActiveAnchor(container, marker) {\n const { isAsideEnabled } = useAside();\n const onScroll = throttleAndDebounce(setActiveLink, 100);\n let prevActiveLink = null;\n onMounted(() => {\n requestAnimationFrame(setActiveLink);\n window.addEventListener('scroll', onScroll);\n });\n onUpdated(() => {\n // sidebar update means a route change\n activateLink(location.hash);\n });\n onUnmounted(() => {\n window.removeEventListener('scroll', onScroll);\n });\n function setActiveLink() {\n if (!isAsideEnabled.value) {\n return;\n }\n const scrollY = window.scrollY;\n const innerHeight = window.innerHeight;\n const offsetHeight = document.body.offsetHeight;\n const isBottom = Math.abs(scrollY + innerHeight - offsetHeight) < 1;\n // resolvedHeaders may be repositioned, hidden or fix positioned\n const headers = resolvedHeaders\n .map(({ element, link }) => ({\n link,\n top: getAbsoluteTop(element)\n }))\n .filter(({ top }) => !Number.isNaN(top))\n .sort((a, b) => a.top - b.top);\n // no headers available for active link\n if (!headers.length) {\n activateLink(null);\n return;\n }\n // page top\n if (scrollY < 1) {\n activateLink(null);\n return;\n }\n // page bottom - highlight last link\n if (isBottom) {\n activateLink(headers[headers.length - 1].link);\n return;\n }\n // find the last header above the top of viewport\n let activeLink = null;\n for (const { link, top } of headers) {\n if (top > scrollY + getScrollOffset() + 4) {\n break;\n }\n activeLink = link;\n }\n activateLink(activeLink);\n }\n function activateLink(hash) {\n if (prevActiveLink) {\n prevActiveLink.classList.remove('active');\n }\n if (hash == null) {\n prevActiveLink = null;\n }\n else {\n prevActiveLink = container.value.querySelector(`a[href=\"${decodeURIComponent(hash)}\"]`);\n }\n const activeLink = prevActiveLink;\n if (activeLink) {\n activeLink.classList.add('active');\n marker.value.style.top = activeLink.offsetTop + 39 + 'px';\n marker.value.style.opacity = '1';\n }\n else {\n marker.value.style.top = '33px';\n marker.value.style.opacity = '0';\n }\n }\n}\nfunction getAbsoluteTop(element) {\n let offsetTop = 0;\n while (element !== document.body) {\n if (element === null) {\n // child element is:\n // - not attached to the DOM (display: none)\n // - set to fixed position (not scrollable)\n // - body or html element (null offsetParent)\n return NaN;\n }\n offsetTop += element.offsetTop;\n element = element.offsetParent;\n }\n return offsetTop;\n}\nfunction buildTree(data, min, max) {\n resolvedHeaders.length = 0;\n const result = [];\n const stack = [];\n data.forEach((item) => {\n const node = { ...item, children: [] };\n let parent = stack[stack.length - 1];\n while (parent && parent.level >= node.level) {\n stack.pop();\n parent = stack[stack.length - 1];\n }\n if (node.element.classList.contains('ignore-header') ||\n (parent && 'shouldIgnore' in parent)) {\n stack.push({ level: node.level, shouldIgnore: true });\n return;\n }\n if (node.level > max || node.level < min)\n return;\n resolvedHeaders.push({ element: node.element, link: node.link });\n if (parent)\n parent.children.push(node);\n else\n result.push(node);\n stack.push(node);\n });\n return result;\n}\n", "import { withBase } from 'vitepress';\nimport { isExternal, treatAsHtml } from '../../shared';\nimport { useData } from '../composables/data';\nexport function throttleAndDebounce(fn, delay) {\n let timeoutId;\n let called = false;\n return () => {\n if (timeoutId)\n clearTimeout(timeoutId);\n if (!called) {\n fn();\n (called = true) && setTimeout(() => (called = false), delay);\n }\n else\n timeoutId = setTimeout(fn, delay);\n };\n}\nexport function ensureStartingSlash(path) {\n return path.startsWith('/') ? path : `/${path}`;\n}\nexport function normalizeLink(url) {\n const { pathname, search, hash, protocol } = new URL(url, 'http://a.com');\n if (isExternal(url) ||\n url.startsWith('#') ||\n !protocol.startsWith('http') ||\n !treatAsHtml(pathname))\n return url;\n const { site } = useData();\n const normalizedPath = pathname.endsWith('/') || pathname.endsWith('.html')\n ? url\n : url.replace(/(?:(^\\.+)\\/)?.*$/, `$1${pathname.replace(/(\\.md)?$/, site.value.cleanUrls ? '' : '.html')}${search}${hash}`);\n return withBase(normalizedPath);\n}\n", "import { useData as useData$ } from 'vitepress';\nexport const useData = useData$;\n", "import { isActive } from '../../shared';\nimport { ensureStartingSlash } from './utils';\n/**\n * Get the `Sidebar` from sidebar option. This method will ensure to get correct\n * sidebar config from `MultiSideBarConfig` with various path combinations such\n * as matching `guide/` and `/guide/`. If no matching config was found, it will\n * return empty array.\n */\nexport function getSidebar(_sidebar, path) {\n if (Array.isArray(_sidebar))\n return addBase(_sidebar);\n if (_sidebar == null)\n return [];\n path = ensureStartingSlash(path);\n const dir = Object.keys(_sidebar)\n .sort((a, b) => {\n return b.split('/').length - a.split('/').length;\n })\n .find((dir) => {\n // make sure the multi sidebar key starts with slash too\n return path.startsWith(ensureStartingSlash(dir));\n });\n const sidebar = dir ? _sidebar[dir] : [];\n return Array.isArray(sidebar)\n ? addBase(sidebar)\n : addBase(sidebar.items, sidebar.base);\n}\n/**\n * Get or generate sidebar group from the given sidebar items.\n */\nexport function getSidebarGroups(sidebar) {\n const groups = [];\n let lastGroupIndex = 0;\n for (const index in sidebar) {\n const item = sidebar[index];\n if (item.items) {\n lastGroupIndex = groups.push(item);\n continue;\n }\n if (!groups[lastGroupIndex]) {\n groups.push({ items: [] });\n }\n groups[lastGroupIndex].items.push(item);\n }\n return groups;\n}\nexport function getFlatSideBarLinks(sidebar) {\n const links = [];\n function recursivelyExtractLinks(items) {\n for (const item of items) {\n if (item.text && item.link) {\n links.push({\n text: item.text,\n link: item.link,\n docFooterText: item.docFooterText\n });\n }\n if (item.items) {\n recursivelyExtractLinks(item.items);\n }\n }\n }\n recursivelyExtractLinks(sidebar);\n return links;\n}\n/**\n * Check if the given sidebar item contains any active link.\n */\nexport function hasActiveLink(path, items) {\n if (Array.isArray(items)) {\n return items.some((item) => hasActiveLink(path, item));\n }\n return isActive(path, items.link)\n ? true\n : items.items\n ? hasActiveLink(path, items.items)\n : false;\n}\nfunction addBase(items, _base) {\n return [...items].map((_item) => {\n const item = { ..._item };\n const base = item.base || _base;\n if (base && item.link)\n item.link = base + item.link;\n if (item.items)\n item.items = addBase(item.items, base);\n return item;\n });\n}\n", "import { useMediaQuery } from '@vueuse/core';\nimport { computed, onMounted, onUnmounted, ref, watch, watchEffect, watchPostEffect } from 'vue';\nimport { isActive } from '../../shared';\nimport { hasActiveLink as containsActiveLink, getSidebar, getSidebarGroups } from '../support/sidebar';\nimport { useData } from './data';\nexport function useSidebar() {\n const { frontmatter, page, theme } = useData();\n const is960 = useMediaQuery('(min-width: 960px)');\n const isOpen = ref(false);\n const _sidebar = computed(() => {\n const sidebarConfig = theme.value.sidebar;\n const relativePath = page.value.relativePath;\n return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : [];\n });\n const sidebar = ref(_sidebar.value);\n watch(_sidebar, (next, prev) => {\n if (JSON.stringify(next) !== JSON.stringify(prev))\n sidebar.value = _sidebar.value;\n });\n const hasSidebar = computed(() => {\n return (frontmatter.value.sidebar !== false &&\n sidebar.value.length > 0 &&\n frontmatter.value.layout !== 'home');\n });\n const leftAside = computed(() => {\n if (hasAside)\n return frontmatter.value.aside == null\n ? theme.value.aside === 'left'\n : frontmatter.value.aside === 'left';\n return false;\n });\n const hasAside = computed(() => {\n if (frontmatter.value.layout === 'home')\n return false;\n if (frontmatter.value.aside != null)\n return !!frontmatter.value.aside;\n return theme.value.aside !== false;\n });\n const isSidebarEnabled = computed(() => hasSidebar.value && is960.value);\n const sidebarGroups = computed(() => {\n return hasSidebar.value ? getSidebarGroups(sidebar.value) : [];\n });\n function open() {\n isOpen.value = true;\n }\n function close() {\n isOpen.value = false;\n }\n function toggle() {\n isOpen.value ? close() : open();\n }\n return {\n isOpen,\n sidebar,\n sidebarGroups,\n hasSidebar,\n hasAside,\n leftAside,\n isSidebarEnabled,\n open,\n close,\n toggle\n };\n}\n/**\n * a11y: cache the element that opened the Sidebar (the menu button) then\n * focus that button again when Menu is closed with Escape key.\n */\nexport function useCloseSidebarOnEscape(isOpen, close) {\n let triggerElement;\n watchEffect(() => {\n triggerElement = isOpen.value\n ? document.activeElement\n : undefined;\n });\n onMounted(() => {\n window.addEventListener('keyup', onEscape);\n });\n onUnmounted(() => {\n window.removeEventListener('keyup', onEscape);\n });\n function onEscape(e) {\n if (e.key === 'Escape' && isOpen.value) {\n close();\n triggerElement?.focus();\n }\n }\n}\nexport function useSidebarControl(item) {\n const { page, hash } = useData();\n const collapsed = ref(false);\n const collapsible = computed(() => {\n return item.value.collapsed != null;\n });\n const isLink = computed(() => {\n return !!item.value.link;\n });\n const isActiveLink = ref(false);\n const updateIsActiveLink = () => {\n isActiveLink.value = isActive(page.value.relativePath, item.value.link);\n };\n watch([page, item, hash], updateIsActiveLink);\n onMounted(updateIsActiveLink);\n const hasActiveLink = computed(() => {\n if (isActiveLink.value) {\n return true;\n }\n return item.value.items\n ? containsActiveLink(page.value.relativePath, item.value.items)\n : false;\n });\n const hasChildren = computed(() => {\n return !!(item.value.items && item.value.items.length);\n });\n watchEffect(() => {\n collapsed.value = !!(collapsible.value && item.value.collapsed);\n });\n watchPostEffect(() => {\n ;\n (isActiveLink.value || hasActiveLink.value) && (collapsed.value = false);\n });\n function toggle() {\n if (collapsible.value) {\n collapsed.value = !collapsed.value;\n }\n }\n return {\n collapsed,\n collapsible,\n isLink,\n isActiveLink,\n hasActiveLink,\n hasChildren,\n toggle\n };\n}\n"], + "mappings": "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", + "names": ["default", "dir", "theme", "theme"] +} diff --git a/docs/.vitepress/cache/deps/_metadata.json b/docs/.vitepress/cache/deps/_metadata.json new file mode 100644 index 0000000..ead6f83 --- /dev/null +++ b/docs/.vitepress/cache/deps/_metadata.json @@ -0,0 +1,58 @@ +{ + "hash": "b8473a4c", + "configHash": "de601e5a", + "lockfileHash": "97b635bf", + "browserHash": "6dc79743", + "optimized": { + "vue": { + "src": "../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js", + "file": "vue.js", + "fileHash": "82d9bd70", + "needsInterop": false + }, + "vitepress > @vue/devtools-api": { + "src": "../../../../node_modules/@vue/devtools-api/dist/index.js", + "file": "vitepress___@vue_devtools-api.js", + "fileHash": "776db5f7", + "needsInterop": false + }, + "vitepress > @vueuse/core": { + "src": "../../../../node_modules/@vueuse/core/index.mjs", + "file": "vitepress___@vueuse_core.js", + "fileHash": "5b890910", + "needsInterop": false + }, + "vitepress > @vueuse/integrations/useFocusTrap": { + "src": "../../../../node_modules/@vueuse/integrations/useFocusTrap.mjs", + "file": "vitepress___@vueuse_integrations_useFocusTrap.js", + "fileHash": "0798c805", + "needsInterop": false + }, + "vitepress > mark.js/src/vanilla.js": { + "src": "../../../../node_modules/mark.js/src/vanilla.js", + "file": "vitepress___mark__js_src_vanilla__js.js", + "fileHash": "ce575f5c", + "needsInterop": false + }, + "vitepress > minisearch": { + "src": "../../../../node_modules/minisearch/dist/es/index.js", + "file": "vitepress___minisearch.js", + "fileHash": "97a74ec0", + "needsInterop": false + }, + "@theme/index": { + "src": "../../../../node_modules/vitepress/dist/client/theme-default/index.js", + "file": "@theme_index.js", + "fileHash": "725ded83", + "needsInterop": false + } + }, + "chunks": { + "chunk-2CLQ7TTZ": { + "file": "chunk-2CLQ7TTZ.js" + }, + "chunk-LE5NDSFD": { + "file": "chunk-LE5NDSFD.js" + } + } +} \ No newline at end of file diff --git a/docs/.vitepress/cache/deps/chunk-2CLQ7TTZ.js b/docs/.vitepress/cache/deps/chunk-2CLQ7TTZ.js new file mode 100644 index 0000000..8cd09fb --- /dev/null +++ b/docs/.vitepress/cache/deps/chunk-2CLQ7TTZ.js @@ -0,0 +1,9719 @@ +import { + Fragment, + TransitionGroup, + computed, + customRef, + defineComponent, + effectScope, + getCurrentInstance, + getCurrentScope, + h, + hasInjectionContext, + inject, + isReactive, + isReadonly, + isRef, + markRaw, + nextTick, + onBeforeMount, + onBeforeUnmount, + onBeforeUpdate, + onMounted, + onScopeDispose, + onUnmounted, + onUpdated, + provide, + reactive, + readonly, + ref, + shallowReactive, + shallowRef, + toRaw, + toRef, + toRefs, + toValue, + unref, + watch, + watchEffect +} from "./chunk-LE5NDSFD.js"; + +// node_modules/@vueuse/shared/index.mjs +function computedEager(fn, options) { + var _a; + const result = shallowRef(); + watchEffect(() => { + result.value = fn(); + }, { + ...options, + flush: (_a = options == null ? void 0 : options.flush) != null ? _a : "sync" + }); + return readonly(result); +} +function computedWithControl(source, fn) { + let v = void 0; + let track; + let trigger; + const dirty = shallowRef(true); + const update = () => { + dirty.value = true; + trigger(); + }; + watch(source, update, { flush: "sync" }); + const get2 = typeof fn === "function" ? fn : fn.get; + const set2 = typeof fn === "function" ? void 0 : fn.set; + const result = customRef((_track, _trigger) => { + track = _track; + trigger = _trigger; + return { + get() { + if (dirty.value) { + v = get2(v); + dirty.value = false; + } + track(); + return v; + }, + set(v2) { + set2 == null ? void 0 : set2(v2); + } + }; + }); + if (Object.isExtensible(result)) + result.trigger = update; + return result; +} +function tryOnScopeDispose(fn) { + if (getCurrentScope()) { + onScopeDispose(fn); + return true; + } + return false; +} +function createEventHook() { + const fns = /* @__PURE__ */ new Set(); + const off = (fn) => { + fns.delete(fn); + }; + const clear = () => { + fns.clear(); + }; + const on = (fn) => { + fns.add(fn); + const offFn = () => off(fn); + tryOnScopeDispose(offFn); + return { + off: offFn + }; + }; + const trigger = (...args) => { + return Promise.all(Array.from(fns).map((fn) => fn(...args))); + }; + return { + on, + off, + trigger, + clear + }; +} +function createGlobalState(stateFactory) { + let initialized = false; + let state; + const scope = effectScope(true); + return (...args) => { + if (!initialized) { + state = scope.run(() => stateFactory(...args)); + initialized = true; + } + return state; + }; +} +var localProvidedStateMap = /* @__PURE__ */ new WeakMap(); +var injectLocal = (...args) => { + var _a; + const key = args[0]; + const instance = (_a = getCurrentInstance()) == null ? void 0 : _a.proxy; + if (instance == null && !hasInjectionContext()) + throw new Error("injectLocal must be called in setup"); + if (instance && localProvidedStateMap.has(instance) && key in localProvidedStateMap.get(instance)) + return localProvidedStateMap.get(instance)[key]; + return inject(...args); +}; +var provideLocal = (key, value) => { + var _a; + const instance = (_a = getCurrentInstance()) == null ? void 0 : _a.proxy; + if (instance == null) + throw new Error("provideLocal must be called in setup"); + if (!localProvidedStateMap.has(instance)) + localProvidedStateMap.set(instance, /* @__PURE__ */ Object.create(null)); + const localProvidedState = localProvidedStateMap.get(instance); + localProvidedState[key] = value; + provide(key, value); +}; +function createInjectionState(composable, options) { + const key = (options == null ? void 0 : options.injectionKey) || Symbol(composable.name || "InjectionState"); + const defaultValue = options == null ? void 0 : options.defaultValue; + const useProvidingState = (...args) => { + const state = composable(...args); + provideLocal(key, state); + return state; + }; + const useInjectedState = () => injectLocal(key, defaultValue); + return [useProvidingState, useInjectedState]; +} +function createRef(value, deep) { + if (deep === true) { + return ref(value); + } else { + return shallowRef(value); + } +} +function createSharedComposable(composable) { + let subscribers = 0; + let state; + let scope; + const dispose = () => { + subscribers -= 1; + if (scope && subscribers <= 0) { + scope.stop(); + state = void 0; + scope = void 0; + } + }; + return (...args) => { + subscribers += 1; + if (!scope) { + scope = effectScope(true); + state = scope.run(() => composable(...args)); + } + tryOnScopeDispose(dispose); + return state; + }; +} +function extendRef(ref2, extend, { enumerable = false, unwrap = true } = {}) { + for (const [key, value] of Object.entries(extend)) { + if (key === "value") + continue; + if (isRef(value) && unwrap) { + Object.defineProperty(ref2, key, { + get() { + return value.value; + }, + set(v) { + value.value = v; + }, + enumerable + }); + } else { + Object.defineProperty(ref2, key, { value, enumerable }); + } + } + return ref2; +} +function get(obj, key) { + if (key == null) + return unref(obj); + return unref(obj)[key]; +} +function isDefined(v) { + return unref(v) != null; +} +function makeDestructurable(obj, arr) { + if (typeof Symbol !== "undefined") { + const clone = { ...obj }; + Object.defineProperty(clone, Symbol.iterator, { + enumerable: false, + value() { + let index = 0; + return { + next: () => ({ + value: arr[index++], + done: index > arr.length + }) + }; + } + }); + return clone; + } else { + return Object.assign([...arr], obj); + } +} +function reactify(fn, options) { + const unrefFn = (options == null ? void 0 : options.computedGetter) === false ? unref : toValue; + return function(...args) { + return computed(() => fn.apply(this, args.map((i) => unrefFn(i)))); + }; +} +function reactifyObject(obj, optionsOrKeys = {}) { + let keys2 = []; + let options; + if (Array.isArray(optionsOrKeys)) { + keys2 = optionsOrKeys; + } else { + options = optionsOrKeys; + const { includeOwnProperties = true } = optionsOrKeys; + keys2.push(...Object.keys(obj)); + if (includeOwnProperties) + keys2.push(...Object.getOwnPropertyNames(obj)); + } + return Object.fromEntries( + keys2.map((key) => { + const value = obj[key]; + return [ + key, + typeof value === "function" ? reactify(value.bind(obj), options) : value + ]; + }) + ); +} +function toReactive(objectRef) { + if (!isRef(objectRef)) + return reactive(objectRef); + const proxy = new Proxy({}, { + get(_, p, receiver) { + return unref(Reflect.get(objectRef.value, p, receiver)); + }, + set(_, p, value) { + if (isRef(objectRef.value[p]) && !isRef(value)) + objectRef.value[p].value = value; + else + objectRef.value[p] = value; + return true; + }, + deleteProperty(_, p) { + return Reflect.deleteProperty(objectRef.value, p); + }, + has(_, p) { + return Reflect.has(objectRef.value, p); + }, + ownKeys() { + return Object.keys(objectRef.value); + }, + getOwnPropertyDescriptor() { + return { + enumerable: true, + configurable: true + }; + } + }); + return reactive(proxy); +} +function reactiveComputed(fn) { + return toReactive(computed(fn)); +} +function reactiveOmit(obj, ...keys2) { + const flatKeys = keys2.flat(); + const predicate = flatKeys[0]; + return reactiveComputed(() => typeof predicate === "function" ? Object.fromEntries(Object.entries(toRefs(obj)).filter(([k, v]) => !predicate(toValue(v), k))) : Object.fromEntries(Object.entries(toRefs(obj)).filter((e) => !flatKeys.includes(e[0])))); +} +var isClient = typeof window !== "undefined" && typeof document !== "undefined"; +var isWorker = typeof WorkerGlobalScope !== "undefined" && globalThis instanceof WorkerGlobalScope; +var isDef = (val) => typeof val !== "undefined"; +var notNullish = (val) => val != null; +var assert = (condition, ...infos) => { + if (!condition) + console.warn(...infos); +}; +var toString = Object.prototype.toString; +var isObject = (val) => toString.call(val) === "[object Object]"; +var now = () => Date.now(); +var timestamp = () => +Date.now(); +var clamp = (n, min, max) => Math.min(max, Math.max(min, n)); +var noop = () => { +}; +var rand = (min, max) => { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min + 1)) + min; +}; +var hasOwn = (val, key) => Object.prototype.hasOwnProperty.call(val, key); +var isIOS = getIsIOS(); +function getIsIOS() { + var _a, _b; + return isClient && ((_a = window == null ? void 0 : window.navigator) == null ? void 0 : _a.userAgent) && (/iP(?:ad|hone|od)/.test(window.navigator.userAgent) || ((_b = window == null ? void 0 : window.navigator) == null ? void 0 : _b.maxTouchPoints) > 2 && /iPad|Macintosh/.test(window == null ? void 0 : window.navigator.userAgent)); +} +function createFilterWrapper(filter, fn) { + function wrapper(...args) { + return new Promise((resolve, reject) => { + Promise.resolve(filter(() => fn.apply(this, args), { fn, thisArg: this, args })).then(resolve).catch(reject); + }); + } + return wrapper; +} +var bypassFilter = (invoke2) => { + return invoke2(); +}; +function debounceFilter(ms, options = {}) { + let timer; + let maxTimer; + let lastRejector = noop; + const _clearTimeout = (timer2) => { + clearTimeout(timer2); + lastRejector(); + lastRejector = noop; + }; + let lastInvoker; + const filter = (invoke2) => { + const duration = toValue(ms); + const maxDuration = toValue(options.maxWait); + if (timer) + _clearTimeout(timer); + if (duration <= 0 || maxDuration !== void 0 && maxDuration <= 0) { + if (maxTimer) { + _clearTimeout(maxTimer); + maxTimer = null; + } + return Promise.resolve(invoke2()); + } + return new Promise((resolve, reject) => { + lastRejector = options.rejectOnCancel ? reject : resolve; + lastInvoker = invoke2; + if (maxDuration && !maxTimer) { + maxTimer = setTimeout(() => { + if (timer) + _clearTimeout(timer); + maxTimer = null; + resolve(lastInvoker()); + }, maxDuration); + } + timer = setTimeout(() => { + if (maxTimer) + _clearTimeout(maxTimer); + maxTimer = null; + resolve(invoke2()); + }, duration); + }); + }; + return filter; +} +function throttleFilter(...args) { + let lastExec = 0; + let timer; + let isLeading = true; + let lastRejector = noop; + let lastValue; + let ms; + let trailing; + let leading; + let rejectOnCancel; + if (!isRef(args[0]) && typeof args[0] === "object") + ({ delay: ms, trailing = true, leading = true, rejectOnCancel = false } = args[0]); + else + [ms, trailing = true, leading = true, rejectOnCancel = false] = args; + const clear = () => { + if (timer) { + clearTimeout(timer); + timer = void 0; + lastRejector(); + lastRejector = noop; + } + }; + const filter = (_invoke) => { + const duration = toValue(ms); + const elapsed = Date.now() - lastExec; + const invoke2 = () => { + return lastValue = _invoke(); + }; + clear(); + if (duration <= 0) { + lastExec = Date.now(); + return invoke2(); + } + if (elapsed > duration && (leading || !isLeading)) { + lastExec = Date.now(); + invoke2(); + } else if (trailing) { + lastValue = new Promise((resolve, reject) => { + lastRejector = rejectOnCancel ? reject : resolve; + timer = setTimeout(() => { + lastExec = Date.now(); + isLeading = true; + resolve(invoke2()); + clear(); + }, Math.max(0, duration - elapsed)); + }); + } + if (!leading && !timer) + timer = setTimeout(() => isLeading = true, duration); + isLeading = false; + return lastValue; + }; + return filter; +} +function pausableFilter(extendFilter = bypassFilter, options = {}) { + const { + initialState = "active" + } = options; + const isActive = toRef2(initialState === "active"); + function pause() { + isActive.value = false; + } + function resume() { + isActive.value = true; + } + const eventFilter = (...args) => { + if (isActive.value) + extendFilter(...args); + }; + return { isActive: readonly(isActive), pause, resume, eventFilter }; +} +function cacheStringFunction(fn) { + const cache = /* @__PURE__ */ Object.create(null); + return (str) => { + const hit = cache[str]; + return hit || (cache[str] = fn(str)); + }; +} +var hyphenateRE = /\B([A-Z])/g; +var hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, "-$1").toLowerCase()); +var camelizeRE = /-(\w)/g; +var camelize = cacheStringFunction((str) => { + return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : ""); +}); +function promiseTimeout(ms, throwOnTimeout = false, reason = "Timeout") { + return new Promise((resolve, reject) => { + if (throwOnTimeout) + setTimeout(() => reject(reason), ms); + else + setTimeout(resolve, ms); + }); +} +function identity(arg) { + return arg; +} +function createSingletonPromise(fn) { + let _promise; + function wrapper() { + if (!_promise) + _promise = fn(); + return _promise; + } + wrapper.reset = async () => { + const _prev = _promise; + _promise = void 0; + if (_prev) + await _prev; + }; + return wrapper; +} +function invoke(fn) { + return fn(); +} +function containsProp(obj, ...props) { + return props.some((k) => k in obj); +} +function increaseWithUnit(target, delta) { + var _a; + if (typeof target === "number") + return target + delta; + const value = ((_a = target.match(/^-?\d+\.?\d*/)) == null ? void 0 : _a[0]) || ""; + const unit = target.slice(value.length); + const result = Number.parseFloat(value) + delta; + if (Number.isNaN(result)) + return target; + return result + unit; +} +function pxValue(px) { + return px.endsWith("rem") ? Number.parseFloat(px) * 16 : Number.parseFloat(px); +} +function objectPick(obj, keys2, omitUndefined = false) { + return keys2.reduce((n, k) => { + if (k in obj) { + if (!omitUndefined || obj[k] !== void 0) + n[k] = obj[k]; + } + return n; + }, {}); +} +function objectOmit(obj, keys2, omitUndefined = false) { + return Object.fromEntries(Object.entries(obj).filter(([key, value]) => { + return (!omitUndefined || value !== void 0) && !keys2.includes(key); + })); +} +function objectEntries(obj) { + return Object.entries(obj); +} +function getLifeCycleTarget(target) { + return target || getCurrentInstance(); +} +function toArray(value) { + return Array.isArray(value) ? value : [value]; +} +function toRef2(...args) { + if (args.length !== 1) + return toRef(...args); + const r = args[0]; + return typeof r === "function" ? readonly(customRef(() => ({ get: r, set: noop }))) : ref(r); +} +var resolveRef = toRef2; +function reactivePick(obj, ...keys2) { + const flatKeys = keys2.flat(); + const predicate = flatKeys[0]; + return reactiveComputed(() => typeof predicate === "function" ? Object.fromEntries(Object.entries(toRefs(obj)).filter(([k, v]) => predicate(toValue(v), k))) : Object.fromEntries(flatKeys.map((k) => [k, toRef2(obj, k)]))); +} +function refAutoReset(defaultValue, afterMs = 1e4) { + return customRef((track, trigger) => { + let value = toValue(defaultValue); + let timer; + const resetAfter = () => setTimeout(() => { + value = toValue(defaultValue); + trigger(); + }, toValue(afterMs)); + tryOnScopeDispose(() => { + clearTimeout(timer); + }); + return { + get() { + track(); + return value; + }, + set(newValue) { + value = newValue; + trigger(); + clearTimeout(timer); + timer = resetAfter(); + } + }; + }); +} +function useDebounceFn(fn, ms = 200, options = {}) { + return createFilterWrapper( + debounceFilter(ms, options), + fn + ); +} +function refDebounced(value, ms = 200, options = {}) { + const debounced = ref(value.value); + const updater = useDebounceFn(() => { + debounced.value = value.value; + }, ms, options); + watch(value, () => updater()); + return debounced; +} +function refDefault(source, defaultValue) { + return computed({ + get() { + var _a; + return (_a = source.value) != null ? _a : defaultValue; + }, + set(value) { + source.value = value; + } + }); +} +function useThrottleFn(fn, ms = 200, trailing = false, leading = true, rejectOnCancel = false) { + return createFilterWrapper( + throttleFilter(ms, trailing, leading, rejectOnCancel), + fn + ); +} +function refThrottled(value, delay = 200, trailing = true, leading = true) { + if (delay <= 0) + return value; + const throttled = ref(value.value); + const updater = useThrottleFn(() => { + throttled.value = value.value; + }, delay, trailing, leading); + watch(value, () => updater()); + return throttled; +} +function refWithControl(initial, options = {}) { + let source = initial; + let track; + let trigger; + const ref2 = customRef((_track, _trigger) => { + track = _track; + trigger = _trigger; + return { + get() { + return get2(); + }, + set(v) { + set2(v); + } + }; + }); + function get2(tracking = true) { + if (tracking) + track(); + return source; + } + function set2(value, triggering = true) { + var _a, _b; + if (value === source) + return; + const old = source; + if (((_a = options.onBeforeChange) == null ? void 0 : _a.call(options, value, old)) === false) + return; + source = value; + (_b = options.onChanged) == null ? void 0 : _b.call(options, value, old); + if (triggering) + trigger(); + } + const untrackedGet = () => get2(false); + const silentSet = (v) => set2(v, false); + const peek = () => get2(false); + const lay = (v) => set2(v, false); + return extendRef( + ref2, + { + get: get2, + set: set2, + untrackedGet, + silentSet, + peek, + lay + }, + { enumerable: true } + ); +} +var controlledRef = refWithControl; +function set(...args) { + if (args.length === 2) { + const [ref2, value] = args; + ref2.value = value; + } + if (args.length === 3) { + const [target, key, value] = args; + target[key] = value; + } +} +function watchWithFilter(source, cb, options = {}) { + const { + eventFilter = bypassFilter, + ...watchOptions + } = options; + return watch( + source, + createFilterWrapper( + eventFilter, + cb + ), + watchOptions + ); +} +function watchPausable(source, cb, options = {}) { + const { + eventFilter: filter, + initialState = "active", + ...watchOptions + } = options; + const { eventFilter, pause, resume, isActive } = pausableFilter(filter, { initialState }); + const stop = watchWithFilter( + source, + cb, + { + ...watchOptions, + eventFilter + } + ); + return { stop, pause, resume, isActive }; +} +function syncRef(left, right, ...[options]) { + const { + flush = "sync", + deep = false, + immediate = true, + direction = "both", + transform = {} + } = options || {}; + const watchers = []; + const transformLTR = "ltr" in transform && transform.ltr || ((v) => v); + const transformRTL = "rtl" in transform && transform.rtl || ((v) => v); + if (direction === "both" || direction === "ltr") { + watchers.push(watchPausable( + left, + (newValue) => { + watchers.forEach((w) => w.pause()); + right.value = transformLTR(newValue); + watchers.forEach((w) => w.resume()); + }, + { flush, deep, immediate } + )); + } + if (direction === "both" || direction === "rtl") { + watchers.push(watchPausable( + right, + (newValue) => { + watchers.forEach((w) => w.pause()); + left.value = transformRTL(newValue); + watchers.forEach((w) => w.resume()); + }, + { flush, deep, immediate } + )); + } + const stop = () => { + watchers.forEach((w) => w.stop()); + }; + return stop; +} +function syncRefs(source, targets, options = {}) { + const { + flush = "sync", + deep = false, + immediate = true + } = options; + const targetsArray = toArray(targets); + return watch( + source, + (newValue) => targetsArray.forEach((target) => target.value = newValue), + { flush, deep, immediate } + ); +} +function toRefs2(objectRef, options = {}) { + if (!isRef(objectRef)) + return toRefs(objectRef); + const result = Array.isArray(objectRef.value) ? Array.from({ length: objectRef.value.length }) : {}; + for (const key in objectRef.value) { + result[key] = customRef(() => ({ + get() { + return objectRef.value[key]; + }, + set(v) { + var _a; + const replaceRef = (_a = toValue(options.replaceRef)) != null ? _a : true; + if (replaceRef) { + if (Array.isArray(objectRef.value)) { + const copy = [...objectRef.value]; + copy[key] = v; + objectRef.value = copy; + } else { + const newObject = { ...objectRef.value, [key]: v }; + Object.setPrototypeOf(newObject, Object.getPrototypeOf(objectRef.value)); + objectRef.value = newObject; + } + } else { + objectRef.value[key] = v; + } + } + })); + } + return result; +} +var toValue2 = toValue; +var resolveUnref = toValue; +function tryOnBeforeMount(fn, sync = true, target) { + const instance = getLifeCycleTarget(target); + if (instance) + onBeforeMount(fn, target); + else if (sync) + fn(); + else + nextTick(fn); +} +function tryOnBeforeUnmount(fn, target) { + const instance = getLifeCycleTarget(target); + if (instance) + onBeforeUnmount(fn, target); +} +function tryOnMounted(fn, sync = true, target) { + const instance = getLifeCycleTarget(); + if (instance) + onMounted(fn, target); + else if (sync) + fn(); + else + nextTick(fn); +} +function tryOnUnmounted(fn, target) { + const instance = getLifeCycleTarget(target); + if (instance) + onUnmounted(fn, target); +} +function createUntil(r, isNot = false) { + function toMatch(condition, { flush = "sync", deep = false, timeout, throwOnTimeout } = {}) { + let stop = null; + const watcher = new Promise((resolve) => { + stop = watch( + r, + (v) => { + if (condition(v) !== isNot) { + if (stop) + stop(); + else + nextTick(() => stop == null ? void 0 : stop()); + resolve(v); + } + }, + { + flush, + deep, + immediate: true + } + ); + }); + const promises = [watcher]; + if (timeout != null) { + promises.push( + promiseTimeout(timeout, throwOnTimeout).then(() => toValue(r)).finally(() => stop == null ? void 0 : stop()) + ); + } + return Promise.race(promises); + } + function toBe(value, options) { + if (!isRef(value)) + return toMatch((v) => v === value, options); + const { flush = "sync", deep = false, timeout, throwOnTimeout } = options != null ? options : {}; + let stop = null; + const watcher = new Promise((resolve) => { + stop = watch( + [r, value], + ([v1, v2]) => { + if (isNot !== (v1 === v2)) { + if (stop) + stop(); + else + nextTick(() => stop == null ? void 0 : stop()); + resolve(v1); + } + }, + { + flush, + deep, + immediate: true + } + ); + }); + const promises = [watcher]; + if (timeout != null) { + promises.push( + promiseTimeout(timeout, throwOnTimeout).then(() => toValue(r)).finally(() => { + stop == null ? void 0 : stop(); + return toValue(r); + }) + ); + } + return Promise.race(promises); + } + function toBeTruthy(options) { + return toMatch((v) => Boolean(v), options); + } + function toBeNull(options) { + return toBe(null, options); + } + function toBeUndefined(options) { + return toBe(void 0, options); + } + function toBeNaN(options) { + return toMatch(Number.isNaN, options); + } + function toContains(value, options) { + return toMatch((v) => { + const array = Array.from(v); + return array.includes(value) || array.includes(toValue(value)); + }, options); + } + function changed(options) { + return changedTimes(1, options); + } + function changedTimes(n = 1, options) { + let count = -1; + return toMatch(() => { + count += 1; + return count >= n; + }, options); + } + if (Array.isArray(toValue(r))) { + const instance = { + toMatch, + toContains, + changed, + changedTimes, + get not() { + return createUntil(r, !isNot); + } + }; + return instance; + } else { + const instance = { + toMatch, + toBe, + toBeTruthy, + toBeNull, + toBeNaN, + toBeUndefined, + changed, + changedTimes, + get not() { + return createUntil(r, !isNot); + } + }; + return instance; + } +} +function until(r) { + return createUntil(r); +} +function defaultComparator(value, othVal) { + return value === othVal; +} +function useArrayDifference(...args) { + var _a, _b; + const list = args[0]; + const values = args[1]; + let compareFn = (_a = args[2]) != null ? _a : defaultComparator; + const { + symmetric = false + } = (_b = args[3]) != null ? _b : {}; + if (typeof compareFn === "string") { + const key = compareFn; + compareFn = (value, othVal) => value[key] === othVal[key]; + } + const diff1 = computed(() => toValue(list).filter((x) => toValue(values).findIndex((y) => compareFn(x, y)) === -1)); + if (symmetric) { + const diff2 = computed(() => toValue(values).filter((x) => toValue(list).findIndex((y) => compareFn(x, y)) === -1)); + return computed(() => symmetric ? [...toValue(diff1), ...toValue(diff2)] : toValue(diff1)); + } else { + return diff1; + } +} +function useArrayEvery(list, fn) { + return computed(() => toValue(list).every((element, index, array) => fn(toValue(element), index, array))); +} +function useArrayFilter(list, fn) { + return computed(() => toValue(list).map((i) => toValue(i)).filter(fn)); +} +function useArrayFind(list, fn) { + return computed(() => toValue( + toValue(list).find((element, index, array) => fn(toValue(element), index, array)) + )); +} +function useArrayFindIndex(list, fn) { + return computed(() => toValue(list).findIndex((element, index, array) => fn(toValue(element), index, array))); +} +function findLast(arr, cb) { + let index = arr.length; + while (index-- > 0) { + if (cb(arr[index], index, arr)) + return arr[index]; + } + return void 0; +} +function useArrayFindLast(list, fn) { + return computed(() => toValue( + !Array.prototype.findLast ? findLast(toValue(list), (element, index, array) => fn(toValue(element), index, array)) : toValue(list).findLast((element, index, array) => fn(toValue(element), index, array)) + )); +} +function isArrayIncludesOptions(obj) { + return isObject(obj) && containsProp(obj, "formIndex", "comparator"); +} +function useArrayIncludes(...args) { + var _a; + const list = args[0]; + const value = args[1]; + let comparator = args[2]; + let formIndex = 0; + if (isArrayIncludesOptions(comparator)) { + formIndex = (_a = comparator.fromIndex) != null ? _a : 0; + comparator = comparator.comparator; + } + if (typeof comparator === "string") { + const key = comparator; + comparator = (element, value2) => element[key] === toValue(value2); + } + comparator = comparator != null ? comparator : (element, value2) => element === toValue(value2); + return computed(() => toValue(list).slice(formIndex).some((element, index, array) => comparator( + toValue(element), + toValue(value), + index, + toValue(array) + ))); +} +function useArrayJoin(list, separator) { + return computed(() => toValue(list).map((i) => toValue(i)).join(toValue(separator))); +} +function useArrayMap(list, fn) { + return computed(() => toValue(list).map((i) => toValue(i)).map(fn)); +} +function useArrayReduce(list, reducer, ...args) { + const reduceCallback = (sum, value, index) => reducer(toValue(sum), toValue(value), index); + return computed(() => { + const resolved = toValue(list); + return args.length ? resolved.reduce(reduceCallback, typeof args[0] === "function" ? toValue(args[0]()) : toValue(args[0])) : resolved.reduce(reduceCallback); + }); +} +function useArraySome(list, fn) { + return computed(() => toValue(list).some((element, index, array) => fn(toValue(element), index, array))); +} +function uniq(array) { + return Array.from(new Set(array)); +} +function uniqueElementsBy(array, fn) { + return array.reduce((acc, v) => { + if (!acc.some((x) => fn(v, x, array))) + acc.push(v); + return acc; + }, []); +} +function useArrayUnique(list, compareFn) { + return computed(() => { + const resolvedList = toValue(list).map((element) => toValue(element)); + return compareFn ? uniqueElementsBy(resolvedList, compareFn) : uniq(resolvedList); + }); +} +function useCounter(initialValue = 0, options = {}) { + let _initialValue = unref(initialValue); + const count = shallowRef(initialValue); + const { + max = Number.POSITIVE_INFINITY, + min = Number.NEGATIVE_INFINITY + } = options; + const inc = (delta = 1) => count.value = Math.max(Math.min(max, count.value + delta), min); + const dec = (delta = 1) => count.value = Math.min(Math.max(min, count.value - delta), max); + const get2 = () => count.value; + const set2 = (val) => count.value = Math.max(min, Math.min(max, val)); + const reset = (val = _initialValue) => { + _initialValue = val; + return set2(val); + }; + return { count, inc, dec, get: get2, set: set2, reset }; +} +var REGEX_PARSE = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[T\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/i; +var REGEX_FORMAT = /[YMDHhms]o|\[([^\]]+)\]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a{1,2}|A{1,2}|m{1,2}|s{1,2}|Z{1,2}|z{1,4}|SSS/g; +function defaultMeridiem(hours, minutes, isLowercase, hasPeriod) { + let m = hours < 12 ? "AM" : "PM"; + if (hasPeriod) + m = m.split("").reduce((acc, curr) => acc += `${curr}.`, ""); + return isLowercase ? m.toLowerCase() : m; +} +function formatOrdinal(num) { + const suffixes = ["th", "st", "nd", "rd"]; + const v = num % 100; + return num + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]); +} +function formatDate(date, formatStr, options = {}) { + var _a; + const years = date.getFullYear(); + const month = date.getMonth(); + const days = date.getDate(); + const hours = date.getHours(); + const minutes = date.getMinutes(); + const seconds = date.getSeconds(); + const milliseconds = date.getMilliseconds(); + const day = date.getDay(); + const meridiem = (_a = options.customMeridiem) != null ? _a : defaultMeridiem; + const stripTimeZone = (dateString) => { + var _a2; + return (_a2 = dateString.split(" ")[1]) != null ? _a2 : ""; + }; + const matches = { + Yo: () => formatOrdinal(years), + YY: () => String(years).slice(-2), + YYYY: () => years, + M: () => month + 1, + Mo: () => formatOrdinal(month + 1), + MM: () => `${month + 1}`.padStart(2, "0"), + MMM: () => date.toLocaleDateString(toValue(options.locales), { month: "short" }), + MMMM: () => date.toLocaleDateString(toValue(options.locales), { month: "long" }), + D: () => String(days), + Do: () => formatOrdinal(days), + DD: () => `${days}`.padStart(2, "0"), + H: () => String(hours), + Ho: () => formatOrdinal(hours), + HH: () => `${hours}`.padStart(2, "0"), + h: () => `${hours % 12 || 12}`.padStart(1, "0"), + ho: () => formatOrdinal(hours % 12 || 12), + hh: () => `${hours % 12 || 12}`.padStart(2, "0"), + m: () => String(minutes), + mo: () => formatOrdinal(minutes), + mm: () => `${minutes}`.padStart(2, "0"), + s: () => String(seconds), + so: () => formatOrdinal(seconds), + ss: () => `${seconds}`.padStart(2, "0"), + SSS: () => `${milliseconds}`.padStart(3, "0"), + d: () => day, + dd: () => date.toLocaleDateString(toValue(options.locales), { weekday: "narrow" }), + ddd: () => date.toLocaleDateString(toValue(options.locales), { weekday: "short" }), + dddd: () => date.toLocaleDateString(toValue(options.locales), { weekday: "long" }), + A: () => meridiem(hours, minutes), + AA: () => meridiem(hours, minutes, false, true), + a: () => meridiem(hours, minutes, true), + aa: () => meridiem(hours, minutes, true, true), + z: () => stripTimeZone(date.toLocaleDateString(toValue(options.locales), { timeZoneName: "shortOffset" })), + zz: () => stripTimeZone(date.toLocaleDateString(toValue(options.locales), { timeZoneName: "shortOffset" })), + zzz: () => stripTimeZone(date.toLocaleDateString(toValue(options.locales), { timeZoneName: "shortOffset" })), + zzzz: () => stripTimeZone(date.toLocaleDateString(toValue(options.locales), { timeZoneName: "longOffset" })) + }; + return formatStr.replace(REGEX_FORMAT, (match, $1) => { + var _a2, _b; + return (_b = $1 != null ? $1 : (_a2 = matches[match]) == null ? void 0 : _a2.call(matches)) != null ? _b : match; + }); +} +function normalizeDate(date) { + if (date === null) + return new Date(Number.NaN); + if (date === void 0) + return /* @__PURE__ */ new Date(); + if (date instanceof Date) + return new Date(date); + if (typeof date === "string" && !/Z$/i.test(date)) { + const d = date.match(REGEX_PARSE); + if (d) { + const m = d[2] - 1 || 0; + const ms = (d[7] || "0").substring(0, 3); + return new Date(d[1], m, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, ms); + } + } + return new Date(date); +} +function useDateFormat(date, formatStr = "HH:mm:ss", options = {}) { + return computed(() => formatDate(normalizeDate(toValue(date)), toValue(formatStr), options)); +} +function useIntervalFn(cb, interval = 1e3, options = {}) { + const { + immediate = true, + immediateCallback = false + } = options; + let timer = null; + const isActive = shallowRef(false); + function clean() { + if (timer) { + clearInterval(timer); + timer = null; + } + } + function pause() { + isActive.value = false; + clean(); + } + function resume() { + const intervalValue = toValue(interval); + if (intervalValue <= 0) + return; + isActive.value = true; + if (immediateCallback) + cb(); + clean(); + if (isActive.value) + timer = setInterval(cb, intervalValue); + } + if (immediate && isClient) + resume(); + if (isRef(interval) || typeof interval === "function") { + const stopWatch = watch(interval, () => { + if (isActive.value && isClient) + resume(); + }); + tryOnScopeDispose(stopWatch); + } + tryOnScopeDispose(pause); + return { + isActive, + pause, + resume + }; +} +function useInterval(interval = 1e3, options = {}) { + const { + controls: exposeControls = false, + immediate = true, + callback + } = options; + const counter = shallowRef(0); + const update = () => counter.value += 1; + const reset = () => { + counter.value = 0; + }; + const controls = useIntervalFn( + callback ? () => { + update(); + callback(counter.value); + } : update, + interval, + { immediate } + ); + if (exposeControls) { + return { + counter, + reset, + ...controls + }; + } else { + return counter; + } +} +function useLastChanged(source, options = {}) { + var _a; + const ms = shallowRef((_a = options.initialValue) != null ? _a : null); + watch( + source, + () => ms.value = timestamp(), + options + ); + return ms; +} +function useTimeoutFn(cb, interval, options = {}) { + const { + immediate = true, + immediateCallback = false + } = options; + const isPending = shallowRef(false); + let timer = null; + function clear() { + if (timer) { + clearTimeout(timer); + timer = null; + } + } + function stop() { + isPending.value = false; + clear(); + } + function start(...args) { + if (immediateCallback) + cb(); + clear(); + isPending.value = true; + timer = setTimeout(() => { + isPending.value = false; + timer = null; + cb(...args); + }, toValue(interval)); + } + if (immediate) { + isPending.value = true; + if (isClient) + start(); + } + tryOnScopeDispose(stop); + return { + isPending: readonly(isPending), + start, + stop + }; +} +function useTimeout(interval = 1e3, options = {}) { + const { + controls: exposeControls = false, + callback + } = options; + const controls = useTimeoutFn( + callback != null ? callback : noop, + interval, + options + ); + const ready = computed(() => !controls.isPending.value); + if (exposeControls) { + return { + ready, + ...controls + }; + } else { + return ready; + } +} +function useToNumber(value, options = {}) { + const { + method = "parseFloat", + radix, + nanToZero + } = options; + return computed(() => { + let resolved = toValue(value); + if (typeof method === "function") + resolved = method(resolved); + else if (typeof resolved === "string") + resolved = Number[method](resolved, radix); + if (nanToZero && Number.isNaN(resolved)) + resolved = 0; + return resolved; + }); +} +function useToString(value) { + return computed(() => `${toValue(value)}`); +} +function useToggle(initialValue = false, options = {}) { + const { + truthyValue = true, + falsyValue = false + } = options; + const valueIsRef = isRef(initialValue); + const _value = shallowRef(initialValue); + function toggle(value) { + if (arguments.length) { + _value.value = value; + return _value.value; + } else { + const truthy = toValue(truthyValue); + _value.value = _value.value === truthy ? toValue(falsyValue) : truthy; + return _value.value; + } + } + if (valueIsRef) + return toggle; + else + return [_value, toggle]; +} +function watchArray(source, cb, options) { + let oldList = (options == null ? void 0 : options.immediate) ? [] : [...typeof source === "function" ? source() : Array.isArray(source) ? source : toValue(source)]; + return watch(source, (newList, _, onCleanup) => { + const oldListRemains = Array.from({ length: oldList.length }); + const added = []; + for (const obj of newList) { + let found = false; + for (let i = 0; i < oldList.length; i++) { + if (!oldListRemains[i] && obj === oldList[i]) { + oldListRemains[i] = true; + found = true; + break; + } + } + if (!found) + added.push(obj); + } + const removed = oldList.filter((_2, i) => !oldListRemains[i]); + cb(newList, oldList, added, removed, onCleanup); + oldList = [...newList]; + }, options); +} +function watchAtMost(source, cb, options) { + const { + count, + ...watchOptions + } = options; + const current = shallowRef(0); + const stop = watchWithFilter( + source, + (...args) => { + current.value += 1; + if (current.value >= toValue(count)) + nextTick(() => stop()); + cb(...args); + }, + watchOptions + ); + return { count: current, stop }; +} +function watchDebounced(source, cb, options = {}) { + const { + debounce = 0, + maxWait = void 0, + ...watchOptions + } = options; + return watchWithFilter( + source, + cb, + { + ...watchOptions, + eventFilter: debounceFilter(debounce, { maxWait }) + } + ); +} +function watchDeep(source, cb, options) { + return watch( + source, + cb, + { + ...options, + deep: true + } + ); +} +function watchIgnorable(source, cb, options = {}) { + const { + eventFilter = bypassFilter, + ...watchOptions + } = options; + const filteredCb = createFilterWrapper( + eventFilter, + cb + ); + let ignoreUpdates; + let ignorePrevAsyncUpdates; + let stop; + if (watchOptions.flush === "sync") { + const ignore = shallowRef(false); + ignorePrevAsyncUpdates = () => { + }; + ignoreUpdates = (updater) => { + ignore.value = true; + updater(); + ignore.value = false; + }; + stop = watch( + source, + (...args) => { + if (!ignore.value) + filteredCb(...args); + }, + watchOptions + ); + } else { + const disposables = []; + const ignoreCounter = shallowRef(0); + const syncCounter = shallowRef(0); + ignorePrevAsyncUpdates = () => { + ignoreCounter.value = syncCounter.value; + }; + disposables.push( + watch( + source, + () => { + syncCounter.value++; + }, + { ...watchOptions, flush: "sync" } + ) + ); + ignoreUpdates = (updater) => { + const syncCounterPrev = syncCounter.value; + updater(); + ignoreCounter.value += syncCounter.value - syncCounterPrev; + }; + disposables.push( + watch( + source, + (...args) => { + const ignore = ignoreCounter.value > 0 && ignoreCounter.value === syncCounter.value; + ignoreCounter.value = 0; + syncCounter.value = 0; + if (ignore) + return; + filteredCb(...args); + }, + watchOptions + ) + ); + stop = () => { + disposables.forEach((fn) => fn()); + }; + } + return { stop, ignoreUpdates, ignorePrevAsyncUpdates }; +} +function watchImmediate(source, cb, options) { + return watch( + source, + cb, + { + ...options, + immediate: true + } + ); +} +function watchOnce(source, cb, options) { + const stop = watch(source, (...args) => { + nextTick(() => stop()); + return cb(...args); + }, options); + return stop; +} +function watchThrottled(source, cb, options = {}) { + const { + throttle = 0, + trailing = true, + leading = true, + ...watchOptions + } = options; + return watchWithFilter( + source, + cb, + { + ...watchOptions, + eventFilter: throttleFilter(throttle, trailing, leading) + } + ); +} +function watchTriggerable(source, cb, options = {}) { + let cleanupFn; + function onEffect() { + if (!cleanupFn) + return; + const fn = cleanupFn; + cleanupFn = void 0; + fn(); + } + function onCleanup(callback) { + cleanupFn = callback; + } + const _cb = (value, oldValue) => { + onEffect(); + return cb(value, oldValue, onCleanup); + }; + const res = watchIgnorable(source, _cb, options); + const { ignoreUpdates } = res; + const trigger = () => { + let res2; + ignoreUpdates(() => { + res2 = _cb(getWatchSources(source), getOldValue(source)); + }); + return res2; + }; + return { + ...res, + trigger + }; +} +function getWatchSources(sources) { + if (isReactive(sources)) + return sources; + if (Array.isArray(sources)) + return sources.map((item) => toValue(item)); + return toValue(sources); +} +function getOldValue(source) { + return Array.isArray(source) ? source.map(() => void 0) : void 0; +} +function whenever(source, cb, options) { + const stop = watch( + source, + (v, ov, onInvalidate) => { + if (v) { + if (options == null ? void 0 : options.once) + nextTick(() => stop()); + cb(v, ov, onInvalidate); + } + }, + { + ...options, + once: false + } + ); + return stop; +} + +// node_modules/@vueuse/core/index.mjs +function computedAsync(evaluationCallback, initialState, optionsOrRef) { + let options; + if (isRef(optionsOrRef)) { + options = { + evaluating: optionsOrRef + }; + } else { + options = optionsOrRef || {}; + } + const { + lazy = false, + evaluating = void 0, + shallow = true, + onError = noop + } = options; + const started = shallowRef(!lazy); + const current = shallow ? shallowRef(initialState) : ref(initialState); + let counter = 0; + watchEffect(async (onInvalidate) => { + if (!started.value) + return; + counter++; + const counterAtBeginning = counter; + let hasFinished = false; + if (evaluating) { + Promise.resolve().then(() => { + evaluating.value = true; + }); + } + try { + const result = await evaluationCallback((cancelCallback) => { + onInvalidate(() => { + if (evaluating) + evaluating.value = false; + if (!hasFinished) + cancelCallback(); + }); + }); + if (counterAtBeginning === counter) + current.value = result; + } catch (e) { + onError(e); + } finally { + if (evaluating && counterAtBeginning === counter) + evaluating.value = false; + hasFinished = true; + } + }); + if (lazy) { + return computed(() => { + started.value = true; + return current.value; + }); + } else { + return current; + } +} +function computedInject(key, options, defaultSource, treatDefaultAsFactory) { + let source = inject(key); + if (defaultSource) + source = inject(key, defaultSource); + if (treatDefaultAsFactory) + source = inject(key, defaultSource, treatDefaultAsFactory); + if (typeof options === "function") { + return computed((ctx) => options(source, ctx)); + } else { + return computed({ + get: (ctx) => options.get(source, ctx), + set: options.set + }); + } +} +function createReusableTemplate(options = {}) { + const { + inheritAttrs = true + } = options; + const render = shallowRef(); + const define = defineComponent({ + setup(_, { slots }) { + return () => { + render.value = slots.default; + }; + } + }); + const reuse = defineComponent({ + inheritAttrs, + props: options.props, + setup(props, { attrs, slots }) { + return () => { + var _a; + if (!render.value && true) + throw new Error("[VueUse] Failed to find the definition of reusable template"); + const vnode = (_a = render.value) == null ? void 0 : _a.call(render, { + ...options.props == null ? keysToCamelKebabCase(attrs) : props, + $slots: slots + }); + return inheritAttrs && (vnode == null ? void 0 : vnode.length) === 1 ? vnode[0] : vnode; + }; + } + }); + return makeDestructurable( + { define, reuse }, + [define, reuse] + ); +} +function keysToCamelKebabCase(obj) { + const newObj = {}; + for (const key in obj) + newObj[camelize(key)] = obj[key]; + return newObj; +} +function createTemplatePromise(options = {}) { + let index = 0; + const instances = ref([]); + function create(...args) { + const props = shallowReactive({ + key: index++, + args, + promise: void 0, + resolve: () => { + }, + reject: () => { + }, + isResolving: false, + options + }); + instances.value.push(props); + props.promise = new Promise((_resolve, _reject) => { + props.resolve = (v) => { + props.isResolving = true; + return _resolve(v); + }; + props.reject = _reject; + }).finally(() => { + props.promise = void 0; + const index2 = instances.value.indexOf(props); + if (index2 !== -1) + instances.value.splice(index2, 1); + }); + return props.promise; + } + function start(...args) { + if (options.singleton && instances.value.length > 0) + return instances.value[0].promise; + return create(...args); + } + const component = defineComponent((_, { slots }) => { + const renderList = () => instances.value.map((props) => { + var _a; + return h(Fragment, { key: props.key }, (_a = slots.default) == null ? void 0 : _a.call(slots, props)); + }); + if (options.transition) + return () => h(TransitionGroup, options.transition, renderList); + return renderList; + }); + component.start = start; + return component; +} +function createUnrefFn(fn) { + return function(...args) { + return fn.apply(this, args.map((i) => toValue(i))); + }; +} +var defaultWindow = isClient ? window : void 0; +var defaultDocument = isClient ? window.document : void 0; +var defaultNavigator = isClient ? window.navigator : void 0; +var defaultLocation = isClient ? window.location : void 0; +function unrefElement(elRef) { + var _a; + const plain = toValue(elRef); + return (_a = plain == null ? void 0 : plain.$el) != null ? _a : plain; +} +function useEventListener(...args) { + const cleanups = []; + const cleanup = () => { + cleanups.forEach((fn) => fn()); + cleanups.length = 0; + }; + const register = (el, event, listener, options) => { + el.addEventListener(event, listener, options); + return () => el.removeEventListener(event, listener, options); + }; + const firstParamTargets = computed(() => { + const test = toArray(toValue(args[0])).filter((e) => e != null); + return test.every((e) => typeof e !== "string") ? test : void 0; + }); + const stopWatch = watchImmediate( + () => { + var _a, _b; + return [ + (_b = (_a = firstParamTargets.value) == null ? void 0 : _a.map((e) => unrefElement(e))) != null ? _b : [defaultWindow].filter((e) => e != null), + toArray(toValue(firstParamTargets.value ? args[1] : args[0])), + toArray(unref(firstParamTargets.value ? args[2] : args[1])), + // @ts-expect-error - TypeScript gets the correct types, but somehow still complains + toValue(firstParamTargets.value ? args[3] : args[2]) + ]; + }, + ([raw_targets, raw_events, raw_listeners, raw_options]) => { + cleanup(); + if (!(raw_targets == null ? void 0 : raw_targets.length) || !(raw_events == null ? void 0 : raw_events.length) || !(raw_listeners == null ? void 0 : raw_listeners.length)) + return; + const optionsClone = isObject(raw_options) ? { ...raw_options } : raw_options; + cleanups.push( + ...raw_targets.flatMap( + (el) => raw_events.flatMap( + (event) => raw_listeners.map((listener) => register(el, event, listener, optionsClone)) + ) + ) + ); + }, + { flush: "post" } + ); + const stop = () => { + stopWatch(); + cleanup(); + }; + tryOnScopeDispose(cleanup); + return stop; +} +var _iOSWorkaround = false; +function onClickOutside(target, handler, options = {}) { + const { window: window2 = defaultWindow, ignore = [], capture = true, detectIframe = false, controls = false } = options; + if (!window2) { + return controls ? { stop: noop, cancel: noop, trigger: noop } : noop; + } + if (isIOS && !_iOSWorkaround) { + _iOSWorkaround = true; + const listenerOptions = { passive: true }; + Array.from(window2.document.body.children).forEach((el) => useEventListener(el, "click", noop, listenerOptions)); + useEventListener(window2.document.documentElement, "click", noop, listenerOptions); + } + let shouldListen = true; + const shouldIgnore = (event) => { + return toValue(ignore).some((target2) => { + if (typeof target2 === "string") { + return Array.from(window2.document.querySelectorAll(target2)).some((el) => el === event.target || event.composedPath().includes(el)); + } else { + const el = unrefElement(target2); + return el && (event.target === el || event.composedPath().includes(el)); + } + }); + }; + function hasMultipleRoots(target2) { + const vm = toValue(target2); + return vm && vm.$.subTree.shapeFlag === 16; + } + function checkMultipleRoots(target2, event) { + const vm = toValue(target2); + const children = vm.$.subTree && vm.$.subTree.children; + if (children == null || !Array.isArray(children)) + return false; + return children.some((child) => child.el === event.target || event.composedPath().includes(child.el)); + } + const listener = (event) => { + const el = unrefElement(target); + if (event.target == null) + return; + if (!(el instanceof Element) && hasMultipleRoots(target) && checkMultipleRoots(target, event)) + return; + if (!el || el === event.target || event.composedPath().includes(el)) + return; + if ("detail" in event && event.detail === 0) + shouldListen = !shouldIgnore(event); + if (!shouldListen) { + shouldListen = true; + return; + } + handler(event); + }; + let isProcessingClick = false; + const cleanup = [ + useEventListener(window2, "click", (event) => { + if (!isProcessingClick) { + isProcessingClick = true; + setTimeout(() => { + isProcessingClick = false; + }, 0); + listener(event); + } + }, { passive: true, capture }), + useEventListener(window2, "pointerdown", (e) => { + const el = unrefElement(target); + shouldListen = !shouldIgnore(e) && !!(el && !e.composedPath().includes(el)); + }, { passive: true }), + detectIframe && useEventListener(window2, "blur", (event) => { + setTimeout(() => { + var _a; + const el = unrefElement(target); + if (((_a = window2.document.activeElement) == null ? void 0 : _a.tagName) === "IFRAME" && !(el == null ? void 0 : el.contains(window2.document.activeElement))) { + handler(event); + } + }, 0); + }, { passive: true }) + ].filter(Boolean); + const stop = () => cleanup.forEach((fn) => fn()); + if (controls) { + return { + stop, + cancel: () => { + shouldListen = false; + }, + trigger: (event) => { + shouldListen = true; + listener(event); + shouldListen = false; + } + }; + } + return stop; +} +function useMounted() { + const isMounted = shallowRef(false); + const instance = getCurrentInstance(); + if (instance) { + onMounted(() => { + isMounted.value = true; + }, instance); + } + return isMounted; +} +function useSupported(callback) { + const isMounted = useMounted(); + return computed(() => { + isMounted.value; + return Boolean(callback()); + }); +} +function useMutationObserver(target, callback, options = {}) { + const { window: window2 = defaultWindow, ...mutationOptions } = options; + let observer; + const isSupported = useSupported(() => window2 && "MutationObserver" in window2); + const cleanup = () => { + if (observer) { + observer.disconnect(); + observer = void 0; + } + }; + const targets = computed(() => { + const value = toValue(target); + const items = toArray(value).map(unrefElement).filter(notNullish); + return new Set(items); + }); + const stopWatch = watch( + () => targets.value, + (targets2) => { + cleanup(); + if (isSupported.value && targets2.size) { + observer = new MutationObserver(callback); + targets2.forEach((el) => observer.observe(el, mutationOptions)); + } + }, + { immediate: true, flush: "post" } + ); + const takeRecords = () => { + return observer == null ? void 0 : observer.takeRecords(); + }; + const stop = () => { + stopWatch(); + cleanup(); + }; + tryOnScopeDispose(stop); + return { + isSupported, + stop, + takeRecords + }; +} +function onElementRemoval(target, callback, options = {}) { + const { + window: window2 = defaultWindow, + document: document2 = window2 == null ? void 0 : window2.document, + flush = "sync" + } = options; + if (!window2 || !document2) + return noop; + let stopFn; + const cleanupAndUpdate = (fn) => { + stopFn == null ? void 0 : stopFn(); + stopFn = fn; + }; + const stopWatch = watchEffect(() => { + const el = unrefElement(target); + if (el) { + const { stop } = useMutationObserver( + document2, + (mutationsList) => { + const targetRemoved = mutationsList.map((mutation) => [...mutation.removedNodes]).flat().some((node) => node === el || node.contains(el)); + if (targetRemoved) { + callback(mutationsList); + } + }, + { + window: window2, + childList: true, + subtree: true + } + ); + cleanupAndUpdate(stop); + } + }, { flush }); + const stopHandle = () => { + stopWatch(); + cleanupAndUpdate(); + }; + tryOnScopeDispose(stopHandle); + return stopHandle; +} +function createKeyPredicate(keyFilter) { + if (typeof keyFilter === "function") + return keyFilter; + else if (typeof keyFilter === "string") + return (event) => event.key === keyFilter; + else if (Array.isArray(keyFilter)) + return (event) => keyFilter.includes(event.key); + return () => true; +} +function onKeyStroke(...args) { + let key; + let handler; + let options = {}; + if (args.length === 3) { + key = args[0]; + handler = args[1]; + options = args[2]; + } else if (args.length === 2) { + if (typeof args[1] === "object") { + key = true; + handler = args[0]; + options = args[1]; + } else { + key = args[0]; + handler = args[1]; + } + } else { + key = true; + handler = args[0]; + } + const { + target = defaultWindow, + eventName = "keydown", + passive = false, + dedupe = false + } = options; + const predicate = createKeyPredicate(key); + const listener = (e) => { + if (e.repeat && toValue(dedupe)) + return; + if (predicate(e)) + handler(e); + }; + return useEventListener(target, eventName, listener, passive); +} +function onKeyDown(key, handler, options = {}) { + return onKeyStroke(key, handler, { ...options, eventName: "keydown" }); +} +function onKeyPressed(key, handler, options = {}) { + return onKeyStroke(key, handler, { ...options, eventName: "keypress" }); +} +function onKeyUp(key, handler, options = {}) { + return onKeyStroke(key, handler, { ...options, eventName: "keyup" }); +} +var DEFAULT_DELAY = 500; +var DEFAULT_THRESHOLD = 10; +function onLongPress(target, handler, options) { + var _a, _b; + const elementRef = computed(() => unrefElement(target)); + let timeout; + let posStart; + let startTimestamp; + let hasLongPressed = false; + function clear() { + if (timeout) { + clearTimeout(timeout); + timeout = void 0; + } + posStart = void 0; + startTimestamp = void 0; + hasLongPressed = false; + } + function onRelease(ev) { + var _a2, _b2, _c; + const [_startTimestamp, _posStart, _hasLongPressed] = [startTimestamp, posStart, hasLongPressed]; + clear(); + if (!(options == null ? void 0 : options.onMouseUp) || !_posStart || !_startTimestamp) + return; + if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value) + return; + if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent) + ev.preventDefault(); + if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop) + ev.stopPropagation(); + const dx = ev.x - _posStart.x; + const dy = ev.y - _posStart.y; + const distance = Math.sqrt(dx * dx + dy * dy); + options.onMouseUp(ev.timeStamp - _startTimestamp, distance, _hasLongPressed); + } + function onDown(ev) { + var _a2, _b2, _c, _d; + if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value) + return; + clear(); + if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent) + ev.preventDefault(); + if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop) + ev.stopPropagation(); + posStart = { + x: ev.x, + y: ev.y + }; + startTimestamp = ev.timeStamp; + timeout = setTimeout( + () => { + hasLongPressed = true; + handler(ev); + }, + (_d = options == null ? void 0 : options.delay) != null ? _d : DEFAULT_DELAY + ); + } + function onMove(ev) { + var _a2, _b2, _c, _d; + if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value) + return; + if (!posStart || (options == null ? void 0 : options.distanceThreshold) === false) + return; + if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent) + ev.preventDefault(); + if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop) + ev.stopPropagation(); + const dx = ev.x - posStart.x; + const dy = ev.y - posStart.y; + const distance = Math.sqrt(dx * dx + dy * dy); + if (distance >= ((_d = options == null ? void 0 : options.distanceThreshold) != null ? _d : DEFAULT_THRESHOLD)) + clear(); + } + const listenerOptions = { + capture: (_a = options == null ? void 0 : options.modifiers) == null ? void 0 : _a.capture, + once: (_b = options == null ? void 0 : options.modifiers) == null ? void 0 : _b.once + }; + const cleanup = [ + useEventListener(elementRef, "pointerdown", onDown, listenerOptions), + useEventListener(elementRef, "pointermove", onMove, listenerOptions), + useEventListener(elementRef, ["pointerup", "pointerleave"], onRelease, listenerOptions) + ]; + const stop = () => cleanup.forEach((fn) => fn()); + return stop; +} +function isFocusedElementEditable() { + const { activeElement, body } = document; + if (!activeElement) + return false; + if (activeElement === body) + return false; + switch (activeElement.tagName) { + case "INPUT": + case "TEXTAREA": + return true; + } + return activeElement.hasAttribute("contenteditable"); +} +function isTypedCharValid({ + keyCode, + metaKey, + ctrlKey, + altKey +}) { + if (metaKey || ctrlKey || altKey) + return false; + if (keyCode >= 48 && keyCode <= 57 || keyCode >= 96 && keyCode <= 105) + return true; + if (keyCode >= 65 && keyCode <= 90) + return true; + return false; +} +function onStartTyping(callback, options = {}) { + const { document: document2 = defaultDocument } = options; + const keydown = (event) => { + if (!isFocusedElementEditable() && isTypedCharValid(event)) { + callback(event); + } + }; + if (document2) + useEventListener(document2, "keydown", keydown, { passive: true }); +} +function templateRef(key, initialValue = null) { + const instance = getCurrentInstance(); + let _trigger = () => { + }; + const element = customRef((track, trigger) => { + _trigger = trigger; + return { + get() { + var _a, _b; + track(); + return (_b = (_a = instance == null ? void 0 : instance.proxy) == null ? void 0 : _a.$refs[key]) != null ? _b : initialValue; + }, + set() { + } + }; + }); + tryOnMounted(_trigger); + onUpdated(_trigger); + return element; +} +function useActiveElement(options = {}) { + var _a; + const { + window: window2 = defaultWindow, + deep = true, + triggerOnRemoval = false + } = options; + const document2 = (_a = options.document) != null ? _a : window2 == null ? void 0 : window2.document; + const getDeepActiveElement = () => { + var _a2; + let element = document2 == null ? void 0 : document2.activeElement; + if (deep) { + while (element == null ? void 0 : element.shadowRoot) + element = (_a2 = element == null ? void 0 : element.shadowRoot) == null ? void 0 : _a2.activeElement; + } + return element; + }; + const activeElement = shallowRef(); + const trigger = () => { + activeElement.value = getDeepActiveElement(); + }; + if (window2) { + const listenerOptions = { + capture: true, + passive: true + }; + useEventListener( + window2, + "blur", + (event) => { + if (event.relatedTarget !== null) + return; + trigger(); + }, + listenerOptions + ); + useEventListener( + window2, + "focus", + trigger, + listenerOptions + ); + } + if (triggerOnRemoval) { + onElementRemoval(activeElement, trigger, { document: document2 }); + } + trigger(); + return activeElement; +} +function useRafFn(fn, options = {}) { + const { + immediate = true, + fpsLimit = void 0, + window: window2 = defaultWindow, + once = false + } = options; + const isActive = shallowRef(false); + const intervalLimit = computed(() => { + return fpsLimit ? 1e3 / toValue(fpsLimit) : null; + }); + let previousFrameTimestamp = 0; + let rafId = null; + function loop(timestamp2) { + if (!isActive.value || !window2) + return; + if (!previousFrameTimestamp) + previousFrameTimestamp = timestamp2; + const delta = timestamp2 - previousFrameTimestamp; + if (intervalLimit.value && delta < intervalLimit.value) { + rafId = window2.requestAnimationFrame(loop); + return; + } + previousFrameTimestamp = timestamp2; + fn({ delta, timestamp: timestamp2 }); + if (once) { + isActive.value = false; + rafId = null; + return; + } + rafId = window2.requestAnimationFrame(loop); + } + function resume() { + if (!isActive.value && window2) { + isActive.value = true; + previousFrameTimestamp = 0; + rafId = window2.requestAnimationFrame(loop); + } + } + function pause() { + isActive.value = false; + if (rafId != null && window2) { + window2.cancelAnimationFrame(rafId); + rafId = null; + } + } + if (immediate) + resume(); + tryOnScopeDispose(pause); + return { + isActive: readonly(isActive), + pause, + resume + }; +} +function useAnimate(target, keyframes, options) { + let config; + let animateOptions; + if (isObject(options)) { + config = options; + animateOptions = objectOmit(options, ["window", "immediate", "commitStyles", "persist", "onReady", "onError"]); + } else { + config = { duration: options }; + animateOptions = options; + } + const { + window: window2 = defaultWindow, + immediate = true, + commitStyles, + persist, + playbackRate: _playbackRate = 1, + onReady, + onError = (e) => { + console.error(e); + } + } = config; + const isSupported = useSupported(() => window2 && HTMLElement && "animate" in HTMLElement.prototype); + const animate = shallowRef(void 0); + const store = shallowReactive({ + startTime: null, + currentTime: null, + timeline: null, + playbackRate: _playbackRate, + pending: false, + playState: immediate ? "idle" : "paused", + replaceState: "active" + }); + const pending = computed(() => store.pending); + const playState = computed(() => store.playState); + const replaceState = computed(() => store.replaceState); + const startTime = computed({ + get() { + return store.startTime; + }, + set(value) { + store.startTime = value; + if (animate.value) + animate.value.startTime = value; + } + }); + const currentTime = computed({ + get() { + return store.currentTime; + }, + set(value) { + store.currentTime = value; + if (animate.value) { + animate.value.currentTime = value; + syncResume(); + } + } + }); + const timeline = computed({ + get() { + return store.timeline; + }, + set(value) { + store.timeline = value; + if (animate.value) + animate.value.timeline = value; + } + }); + const playbackRate = computed({ + get() { + return store.playbackRate; + }, + set(value) { + store.playbackRate = value; + if (animate.value) + animate.value.playbackRate = value; + } + }); + const play = () => { + if (animate.value) { + try { + animate.value.play(); + syncResume(); + } catch (e) { + syncPause(); + onError(e); + } + } else { + update(); + } + }; + const pause = () => { + var _a; + try { + (_a = animate.value) == null ? void 0 : _a.pause(); + syncPause(); + } catch (e) { + onError(e); + } + }; + const reverse = () => { + var _a; + if (!animate.value) + update(); + try { + (_a = animate.value) == null ? void 0 : _a.reverse(); + syncResume(); + } catch (e) { + syncPause(); + onError(e); + } + }; + const finish = () => { + var _a; + try { + (_a = animate.value) == null ? void 0 : _a.finish(); + syncPause(); + } catch (e) { + onError(e); + } + }; + const cancel = () => { + var _a; + try { + (_a = animate.value) == null ? void 0 : _a.cancel(); + syncPause(); + } catch (e) { + onError(e); + } + }; + watch(() => unrefElement(target), (el) => { + if (el) { + update(); + } else { + animate.value = void 0; + } + }); + watch(() => keyframes, (value) => { + if (animate.value) { + update(); + const targetEl = unrefElement(target); + if (targetEl) { + animate.value.effect = new KeyframeEffect( + targetEl, + toValue(value), + animateOptions + ); + } + } + }, { deep: true }); + tryOnMounted(() => update(true), false); + tryOnScopeDispose(cancel); + function update(init) { + const el = unrefElement(target); + if (!isSupported.value || !el) + return; + if (!animate.value) + animate.value = el.animate(toValue(keyframes), animateOptions); + if (persist) + animate.value.persist(); + if (_playbackRate !== 1) + animate.value.playbackRate = _playbackRate; + if (init && !immediate) + animate.value.pause(); + else + syncResume(); + onReady == null ? void 0 : onReady(animate.value); + } + const listenerOptions = { passive: true }; + useEventListener(animate, ["cancel", "finish", "remove"], syncPause, listenerOptions); + useEventListener(animate, "finish", () => { + var _a; + if (commitStyles) + (_a = animate.value) == null ? void 0 : _a.commitStyles(); + }, listenerOptions); + const { resume: resumeRef, pause: pauseRef } = useRafFn(() => { + if (!animate.value) + return; + store.pending = animate.value.pending; + store.playState = animate.value.playState; + store.replaceState = animate.value.replaceState; + store.startTime = animate.value.startTime; + store.currentTime = animate.value.currentTime; + store.timeline = animate.value.timeline; + store.playbackRate = animate.value.playbackRate; + }, { immediate: false }); + function syncResume() { + if (isSupported.value) + resumeRef(); + } + function syncPause() { + if (isSupported.value && window2) + window2.requestAnimationFrame(pauseRef); + } + return { + isSupported, + animate, + // actions + play, + pause, + reverse, + finish, + cancel, + // state + pending, + playState, + replaceState, + startTime, + currentTime, + timeline, + playbackRate + }; +} +function useAsyncQueue(tasks, options) { + const { + interrupt = true, + onError = noop, + onFinished = noop, + signal + } = options || {}; + const promiseState = { + aborted: "aborted", + fulfilled: "fulfilled", + pending: "pending", + rejected: "rejected" + }; + const initialResult = Array.from(Array.from({ length: tasks.length }), () => ({ state: promiseState.pending, data: null })); + const result = reactive(initialResult); + const activeIndex = shallowRef(-1); + if (!tasks || tasks.length === 0) { + onFinished(); + return { + activeIndex, + result + }; + } + function updateResult(state, res) { + activeIndex.value++; + result[activeIndex.value].data = res; + result[activeIndex.value].state = state; + } + tasks.reduce((prev, curr) => { + return prev.then((prevRes) => { + var _a; + if (signal == null ? void 0 : signal.aborted) { + updateResult(promiseState.aborted, new Error("aborted")); + return; + } + if (((_a = result[activeIndex.value]) == null ? void 0 : _a.state) === promiseState.rejected && interrupt) { + onFinished(); + return; + } + const done = curr(prevRes).then((currentRes) => { + updateResult(promiseState.fulfilled, currentRes); + if (activeIndex.value === tasks.length - 1) + onFinished(); + return currentRes; + }); + if (!signal) + return done; + return Promise.race([done, whenAborted(signal)]); + }).catch((e) => { + if (signal == null ? void 0 : signal.aborted) { + updateResult(promiseState.aborted, e); + return e; + } + updateResult(promiseState.rejected, e); + onError(); + return e; + }); + }, Promise.resolve()); + return { + activeIndex, + result + }; +} +function whenAborted(signal) { + return new Promise((resolve, reject) => { + const error = new Error("aborted"); + if (signal.aborted) + reject(error); + else + signal.addEventListener("abort", () => reject(error), { once: true }); + }); +} +function useAsyncState(promise, initialState, options) { + const { + immediate = true, + delay = 0, + onError = noop, + onSuccess = noop, + resetOnExecute = true, + shallow = true, + throwError + } = options != null ? options : {}; + const state = shallow ? shallowRef(initialState) : ref(initialState); + const isReady = shallowRef(false); + const isLoading = shallowRef(false); + const error = shallowRef(void 0); + async function execute(delay2 = 0, ...args) { + if (resetOnExecute) + state.value = initialState; + error.value = void 0; + isReady.value = false; + isLoading.value = true; + if (delay2 > 0) + await promiseTimeout(delay2); + const _promise = typeof promise === "function" ? promise(...args) : promise; + try { + const data = await _promise; + state.value = data; + isReady.value = true; + onSuccess(data); + } catch (e) { + error.value = e; + onError(e); + if (throwError) + throw e; + } finally { + isLoading.value = false; + } + return state.value; + } + if (immediate) { + execute(delay); + } + const shell = { + state, + isReady, + isLoading, + error, + execute + }; + function waitUntilIsLoaded() { + return new Promise((resolve, reject) => { + until(isLoading).toBe(false).then(() => resolve(shell)).catch(reject); + }); + } + return { + ...shell, + then(onFulfilled, onRejected) { + return waitUntilIsLoaded().then(onFulfilled, onRejected); + } + }; +} +var defaults = { + array: (v) => JSON.stringify(v), + object: (v) => JSON.stringify(v), + set: (v) => JSON.stringify(Array.from(v)), + map: (v) => JSON.stringify(Object.fromEntries(v)), + null: () => "" +}; +function getDefaultSerialization(target) { + if (!target) + return defaults.null; + if (target instanceof Map) + return defaults.map; + else if (target instanceof Set) + return defaults.set; + else if (Array.isArray(target)) + return defaults.array; + else + return defaults.object; +} +function useBase64(target, options) { + const base64 = shallowRef(""); + const promise = shallowRef(); + function execute() { + if (!isClient) + return; + promise.value = new Promise((resolve, reject) => { + try { + const _target = toValue(target); + if (_target == null) { + resolve(""); + } else if (typeof _target === "string") { + resolve(blobToBase64(new Blob([_target], { type: "text/plain" }))); + } else if (_target instanceof Blob) { + resolve(blobToBase64(_target)); + } else if (_target instanceof ArrayBuffer) { + resolve(window.btoa(String.fromCharCode(...new Uint8Array(_target)))); + } else if (_target instanceof HTMLCanvasElement) { + resolve(_target.toDataURL(options == null ? void 0 : options.type, options == null ? void 0 : options.quality)); + } else if (_target instanceof HTMLImageElement) { + const img = _target.cloneNode(false); + img.crossOrigin = "Anonymous"; + imgLoaded(img).then(() => { + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext("2d"); + canvas.width = img.width; + canvas.height = img.height; + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + resolve(canvas.toDataURL(options == null ? void 0 : options.type, options == null ? void 0 : options.quality)); + }).catch(reject); + } else if (typeof _target === "object") { + const _serializeFn = (options == null ? void 0 : options.serializer) || getDefaultSerialization(_target); + const serialized = _serializeFn(_target); + return resolve(blobToBase64(new Blob([serialized], { type: "application/json" }))); + } else { + reject(new Error("target is unsupported types")); + } + } catch (error) { + reject(error); + } + }); + promise.value.then((res) => { + base64.value = (options == null ? void 0 : options.dataUrl) === false ? res.replace(/^data:.*?;base64,/, "") : res; + }); + return promise.value; + } + if (isRef(target) || typeof target === "function") + watch(target, execute, { immediate: true }); + else + execute(); + return { + base64, + promise, + execute + }; +} +function imgLoaded(img) { + return new Promise((resolve, reject) => { + if (!img.complete) { + img.onload = () => { + resolve(); + }; + img.onerror = reject; + } else { + resolve(); + } + }); +} +function blobToBase64(blob) { + return new Promise((resolve, reject) => { + const fr = new FileReader(); + fr.onload = (e) => { + resolve(e.target.result); + }; + fr.onerror = reject; + fr.readAsDataURL(blob); + }); +} +function useBattery(options = {}) { + const { navigator: navigator2 = defaultNavigator } = options; + const events2 = ["chargingchange", "chargingtimechange", "dischargingtimechange", "levelchange"]; + const isSupported = useSupported(() => navigator2 && "getBattery" in navigator2 && typeof navigator2.getBattery === "function"); + const charging = shallowRef(false); + const chargingTime = shallowRef(0); + const dischargingTime = shallowRef(0); + const level = shallowRef(1); + let battery; + function updateBatteryInfo() { + charging.value = this.charging; + chargingTime.value = this.chargingTime || 0; + dischargingTime.value = this.dischargingTime || 0; + level.value = this.level; + } + if (isSupported.value) { + navigator2.getBattery().then((_battery) => { + battery = _battery; + updateBatteryInfo.call(battery); + useEventListener(battery, events2, updateBatteryInfo, { passive: true }); + }); + } + return { + isSupported, + charging, + chargingTime, + dischargingTime, + level + }; +} +function useBluetooth(options) { + let { + acceptAllDevices = false + } = options || {}; + const { + filters = void 0, + optionalServices = void 0, + navigator: navigator2 = defaultNavigator + } = options || {}; + const isSupported = useSupported(() => navigator2 && "bluetooth" in navigator2); + const device = shallowRef(); + const error = shallowRef(null); + watch(device, () => { + connectToBluetoothGATTServer(); + }); + async function requestDevice() { + if (!isSupported.value) + return; + error.value = null; + if (filters && filters.length > 0) + acceptAllDevices = false; + try { + device.value = await (navigator2 == null ? void 0 : navigator2.bluetooth.requestDevice({ + acceptAllDevices, + filters, + optionalServices + })); + } catch (err) { + error.value = err; + } + } + const server = shallowRef(); + const isConnected = shallowRef(false); + function reset() { + isConnected.value = false; + device.value = void 0; + server.value = void 0; + } + async function connectToBluetoothGATTServer() { + error.value = null; + if (device.value && device.value.gatt) { + useEventListener(device, "gattserverdisconnected", reset, { passive: true }); + try { + server.value = await device.value.gatt.connect(); + isConnected.value = server.value.connected; + } catch (err) { + error.value = err; + } + } + } + tryOnMounted(() => { + var _a; + if (device.value) + (_a = device.value.gatt) == null ? void 0 : _a.connect(); + }); + tryOnScopeDispose(() => { + var _a; + if (device.value) + (_a = device.value.gatt) == null ? void 0 : _a.disconnect(); + }); + return { + isSupported, + isConnected: readonly(isConnected), + // Device: + device, + requestDevice, + // Server: + server, + // Errors: + error + }; +} +var ssrWidthSymbol = Symbol("vueuse-ssr-width"); +function useSSRWidth() { + const ssrWidth = hasInjectionContext() ? injectLocal(ssrWidthSymbol, null) : null; + return typeof ssrWidth === "number" ? ssrWidth : void 0; +} +function provideSSRWidth(width, app) { + if (app !== void 0) { + app.provide(ssrWidthSymbol, width); + } else { + provideLocal(ssrWidthSymbol, width); + } +} +function useMediaQuery(query, options = {}) { + const { window: window2 = defaultWindow, ssrWidth = useSSRWidth() } = options; + const isSupported = useSupported(() => window2 && "matchMedia" in window2 && typeof window2.matchMedia === "function"); + const ssrSupport = shallowRef(typeof ssrWidth === "number"); + const mediaQuery = shallowRef(); + const matches = shallowRef(false); + const handler = (event) => { + matches.value = event.matches; + }; + watchEffect(() => { + if (ssrSupport.value) { + ssrSupport.value = !isSupported.value; + const queryStrings = toValue(query).split(","); + matches.value = queryStrings.some((queryString) => { + const not = queryString.includes("not all"); + const minWidth = queryString.match(/\(\s*min-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/); + const maxWidth = queryString.match(/\(\s*max-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/); + let res = Boolean(minWidth || maxWidth); + if (minWidth && res) { + res = ssrWidth >= pxValue(minWidth[1]); + } + if (maxWidth && res) { + res = ssrWidth <= pxValue(maxWidth[1]); + } + return not ? !res : res; + }); + return; + } + if (!isSupported.value) + return; + mediaQuery.value = window2.matchMedia(toValue(query)); + matches.value = mediaQuery.value.matches; + }); + useEventListener(mediaQuery, "change", handler, { passive: true }); + return computed(() => matches.value); +} +var breakpointsTailwind = { + "sm": 640, + "md": 768, + "lg": 1024, + "xl": 1280, + "2xl": 1536 +}; +var breakpointsBootstrapV5 = { + xs: 0, + sm: 576, + md: 768, + lg: 992, + xl: 1200, + xxl: 1400 +}; +var breakpointsVuetifyV2 = { + xs: 0, + sm: 600, + md: 960, + lg: 1264, + xl: 1904 +}; +var breakpointsVuetifyV3 = { + xs: 0, + sm: 600, + md: 960, + lg: 1280, + xl: 1920, + xxl: 2560 +}; +var breakpointsVuetify = breakpointsVuetifyV2; +var breakpointsAntDesign = { + xs: 480, + sm: 576, + md: 768, + lg: 992, + xl: 1200, + xxl: 1600 +}; +var breakpointsQuasar = { + xs: 0, + sm: 600, + md: 1024, + lg: 1440, + xl: 1920 +}; +var breakpointsSematic = { + mobileS: 320, + mobileM: 375, + mobileL: 425, + tablet: 768, + laptop: 1024, + laptopL: 1440, + desktop4K: 2560 +}; +var breakpointsMasterCss = { + "3xs": 360, + "2xs": 480, + "xs": 600, + "sm": 768, + "md": 1024, + "lg": 1280, + "xl": 1440, + "2xl": 1600, + "3xl": 1920, + "4xl": 2560 +}; +var breakpointsPrimeFlex = { + sm: 576, + md: 768, + lg: 992, + xl: 1200 +}; +var breakpointsElement = { + xs: 0, + sm: 768, + md: 992, + lg: 1200, + xl: 1920 +}; +function useBreakpoints(breakpoints, options = {}) { + function getValue2(k, delta) { + let v = toValue(breakpoints[toValue(k)]); + if (delta != null) + v = increaseWithUnit(v, delta); + if (typeof v === "number") + v = `${v}px`; + return v; + } + const { window: window2 = defaultWindow, strategy = "min-width", ssrWidth = useSSRWidth() } = options; + const ssrSupport = typeof ssrWidth === "number"; + const mounted = ssrSupport ? shallowRef(false) : { value: true }; + if (ssrSupport) { + tryOnMounted(() => mounted.value = !!window2); + } + function match(query, size) { + if (!mounted.value && ssrSupport) { + return query === "min" ? ssrWidth >= pxValue(size) : ssrWidth <= pxValue(size); + } + if (!window2) + return false; + return window2.matchMedia(`(${query}-width: ${size})`).matches; + } + const greaterOrEqual = (k) => { + return useMediaQuery(() => `(min-width: ${getValue2(k)})`, options); + }; + const smallerOrEqual = (k) => { + return useMediaQuery(() => `(max-width: ${getValue2(k)})`, options); + }; + const shortcutMethods = Object.keys(breakpoints).reduce((shortcuts, k) => { + Object.defineProperty(shortcuts, k, { + get: () => strategy === "min-width" ? greaterOrEqual(k) : smallerOrEqual(k), + enumerable: true, + configurable: true + }); + return shortcuts; + }, {}); + function current() { + const points = Object.keys(breakpoints).map((k) => [k, shortcutMethods[k], pxValue(getValue2(k))]).sort((a, b) => a[2] - b[2]); + return computed(() => points.filter(([, v]) => v.value).map(([k]) => k)); + } + return Object.assign(shortcutMethods, { + greaterOrEqual, + smallerOrEqual, + greater(k) { + return useMediaQuery(() => `(min-width: ${getValue2(k, 0.1)})`, options); + }, + smaller(k) { + return useMediaQuery(() => `(max-width: ${getValue2(k, -0.1)})`, options); + }, + between(a, b) { + return useMediaQuery(() => `(min-width: ${getValue2(a)}) and (max-width: ${getValue2(b, -0.1)})`, options); + }, + isGreater(k) { + return match("min", getValue2(k, 0.1)); + }, + isGreaterOrEqual(k) { + return match("min", getValue2(k)); + }, + isSmaller(k) { + return match("max", getValue2(k, -0.1)); + }, + isSmallerOrEqual(k) { + return match("max", getValue2(k)); + }, + isInBetween(a, b) { + return match("min", getValue2(a)) && match("max", getValue2(b, -0.1)); + }, + current, + active() { + const bps = current(); + return computed(() => bps.value.length === 0 ? "" : bps.value.at(strategy === "min-width" ? -1 : 0)); + } + }); +} +function useBroadcastChannel(options) { + const { + name, + window: window2 = defaultWindow + } = options; + const isSupported = useSupported(() => window2 && "BroadcastChannel" in window2); + const isClosed = shallowRef(false); + const channel = ref(); + const data = ref(); + const error = shallowRef(null); + const post = (data2) => { + if (channel.value) + channel.value.postMessage(data2); + }; + const close = () => { + if (channel.value) + channel.value.close(); + isClosed.value = true; + }; + if (isSupported.value) { + tryOnMounted(() => { + error.value = null; + channel.value = new BroadcastChannel(name); + const listenerOptions = { + passive: true + }; + useEventListener(channel, "message", (e) => { + data.value = e.data; + }, listenerOptions); + useEventListener(channel, "messageerror", (e) => { + error.value = e; + }, listenerOptions); + useEventListener(channel, "close", () => { + isClosed.value = true; + }, listenerOptions); + }); + } + tryOnScopeDispose(() => { + close(); + }); + return { + isSupported, + channel, + data, + post, + close, + error, + isClosed + }; +} +var WRITABLE_PROPERTIES = [ + "hash", + "host", + "hostname", + "href", + "pathname", + "port", + "protocol", + "search" +]; +function useBrowserLocation(options = {}) { + const { window: window2 = defaultWindow } = options; + const refs = Object.fromEntries( + WRITABLE_PROPERTIES.map((key) => [key, ref()]) + ); + for (const [key, ref2] of objectEntries(refs)) { + watch(ref2, (value) => { + if (!(window2 == null ? void 0 : window2.location) || window2.location[key] === value) + return; + window2.location[key] = value; + }); + } + const buildState = (trigger) => { + var _a; + const { state: state2, length } = (window2 == null ? void 0 : window2.history) || {}; + const { origin } = (window2 == null ? void 0 : window2.location) || {}; + for (const key of WRITABLE_PROPERTIES) + refs[key].value = (_a = window2 == null ? void 0 : window2.location) == null ? void 0 : _a[key]; + return reactive({ + trigger, + state: state2, + length, + origin, + ...refs + }); + }; + const state = ref(buildState("load")); + if (window2) { + const listenerOptions = { passive: true }; + useEventListener(window2, "popstate", () => state.value = buildState("popstate"), listenerOptions); + useEventListener(window2, "hashchange", () => state.value = buildState("hashchange"), listenerOptions); + } + return state; +} +function useCached(refValue, comparator = (a, b) => a === b, options) { + const { deepRefs = true, ...watchOptions } = options || {}; + const cachedValue = createRef(refValue.value, deepRefs); + watch(() => refValue.value, (value) => { + if (!comparator(value, cachedValue.value)) + cachedValue.value = value; + }, watchOptions); + return cachedValue; +} +function usePermission(permissionDesc, options = {}) { + const { + controls = false, + navigator: navigator2 = defaultNavigator + } = options; + const isSupported = useSupported(() => navigator2 && "permissions" in navigator2); + const permissionStatus = shallowRef(); + const desc = typeof permissionDesc === "string" ? { name: permissionDesc } : permissionDesc; + const state = shallowRef(); + const update = () => { + var _a, _b; + state.value = (_b = (_a = permissionStatus.value) == null ? void 0 : _a.state) != null ? _b : "prompt"; + }; + useEventListener(permissionStatus, "change", update, { passive: true }); + const query = createSingletonPromise(async () => { + if (!isSupported.value) + return; + if (!permissionStatus.value) { + try { + permissionStatus.value = await navigator2.permissions.query(desc); + } catch (e) { + permissionStatus.value = void 0; + } finally { + update(); + } + } + if (controls) + return toRaw(permissionStatus.value); + }); + query(); + if (controls) { + return { + state, + isSupported, + query + }; + } else { + return state; + } +} +function useClipboard(options = {}) { + const { + navigator: navigator2 = defaultNavigator, + read = false, + source, + copiedDuring = 1500, + legacy = false + } = options; + const isClipboardApiSupported = useSupported(() => navigator2 && "clipboard" in navigator2); + const permissionRead = usePermission("clipboard-read"); + const permissionWrite = usePermission("clipboard-write"); + const isSupported = computed(() => isClipboardApiSupported.value || legacy); + const text = shallowRef(""); + const copied = shallowRef(false); + const timeout = useTimeoutFn(() => copied.value = false, copiedDuring, { immediate: false }); + async function updateText() { + let useLegacy = !(isClipboardApiSupported.value && isAllowed(permissionRead.value)); + if (!useLegacy) { + try { + text.value = await navigator2.clipboard.readText(); + } catch (e) { + useLegacy = true; + } + } + if (useLegacy) { + text.value = legacyRead(); + } + } + if (isSupported.value && read) + useEventListener(["copy", "cut"], updateText, { passive: true }); + async function copy(value = toValue(source)) { + if (isSupported.value && value != null) { + let useLegacy = !(isClipboardApiSupported.value && isAllowed(permissionWrite.value)); + if (!useLegacy) { + try { + await navigator2.clipboard.writeText(value); + } catch (e) { + useLegacy = true; + } + } + if (useLegacy) + legacyCopy(value); + text.value = value; + copied.value = true; + timeout.start(); + } + } + function legacyCopy(value) { + const ta = document.createElement("textarea"); + ta.value = value != null ? value : ""; + ta.style.position = "absolute"; + ta.style.opacity = "0"; + document.body.appendChild(ta); + ta.select(); + document.execCommand("copy"); + ta.remove(); + } + function legacyRead() { + var _a, _b, _c; + return (_c = (_b = (_a = document == null ? void 0 : document.getSelection) == null ? void 0 : _a.call(document)) == null ? void 0 : _b.toString()) != null ? _c : ""; + } + function isAllowed(status) { + return status === "granted" || status === "prompt"; + } + return { + isSupported, + text, + copied, + copy + }; +} +function useClipboardItems(options = {}) { + const { + navigator: navigator2 = defaultNavigator, + read = false, + source, + copiedDuring = 1500 + } = options; + const isSupported = useSupported(() => navigator2 && "clipboard" in navigator2); + const content = ref([]); + const copied = shallowRef(false); + const timeout = useTimeoutFn(() => copied.value = false, copiedDuring, { immediate: false }); + function updateContent() { + if (isSupported.value) { + navigator2.clipboard.read().then((items) => { + content.value = items; + }); + } + } + if (isSupported.value && read) + useEventListener(["copy", "cut"], updateContent, { passive: true }); + async function copy(value = toValue(source)) { + if (isSupported.value && value != null) { + await navigator2.clipboard.write(value); + content.value = value; + copied.value = true; + timeout.start(); + } + } + return { + isSupported, + content, + copied, + copy + }; +} +function cloneFnJSON(source) { + return JSON.parse(JSON.stringify(source)); +} +function useCloned(source, options = {}) { + const cloned = ref({}); + const isModified = shallowRef(false); + let _lastSync = false; + const { + manual, + clone = cloneFnJSON, + // watch options + deep = true, + immediate = true + } = options; + watch(cloned, () => { + if (_lastSync) { + _lastSync = false; + return; + } + isModified.value = true; + }, { + deep: true, + flush: "sync" + }); + function sync() { + _lastSync = true; + isModified.value = false; + cloned.value = clone(toValue(source)); + } + if (!manual && (isRef(source) || typeof source === "function")) { + watch(source, sync, { + ...options, + deep, + immediate + }); + } else { + sync(); + } + return { cloned, isModified, sync }; +} +var _global = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {}; +var globalKey = "__vueuse_ssr_handlers__"; +var handlers = getHandlers(); +function getHandlers() { + if (!(globalKey in _global)) + _global[globalKey] = _global[globalKey] || {}; + return _global[globalKey]; +} +function getSSRHandler(key, fallback) { + return handlers[key] || fallback; +} +function setSSRHandler(key, fn) { + handlers[key] = fn; +} +function usePreferredDark(options) { + return useMediaQuery("(prefers-color-scheme: dark)", options); +} +function guessSerializerType(rawInit) { + return rawInit == null ? "any" : rawInit instanceof Set ? "set" : rawInit instanceof Map ? "map" : rawInit instanceof Date ? "date" : typeof rawInit === "boolean" ? "boolean" : typeof rawInit === "string" ? "string" : typeof rawInit === "object" ? "object" : !Number.isNaN(rawInit) ? "number" : "any"; +} +var StorageSerializers = { + boolean: { + read: (v) => v === "true", + write: (v) => String(v) + }, + object: { + read: (v) => JSON.parse(v), + write: (v) => JSON.stringify(v) + }, + number: { + read: (v) => Number.parseFloat(v), + write: (v) => String(v) + }, + any: { + read: (v) => v, + write: (v) => String(v) + }, + string: { + read: (v) => v, + write: (v) => String(v) + }, + map: { + read: (v) => new Map(JSON.parse(v)), + write: (v) => JSON.stringify(Array.from(v.entries())) + }, + set: { + read: (v) => new Set(JSON.parse(v)), + write: (v) => JSON.stringify(Array.from(v)) + }, + date: { + read: (v) => new Date(v), + write: (v) => v.toISOString() + } +}; +var customStorageEventName = "vueuse-storage"; +function useStorage(key, defaults2, storage, options = {}) { + var _a; + const { + flush = "pre", + deep = true, + listenToStorageChanges = true, + writeDefaults = true, + mergeDefaults = false, + shallow, + window: window2 = defaultWindow, + eventFilter, + onError = (e) => { + console.error(e); + }, + initOnMounted + } = options; + const data = (shallow ? shallowRef : ref)(typeof defaults2 === "function" ? defaults2() : defaults2); + const keyComputed = computed(() => toValue(key)); + if (!storage) { + try { + storage = getSSRHandler("getDefaultStorage", () => { + var _a2; + return (_a2 = defaultWindow) == null ? void 0 : _a2.localStorage; + })(); + } catch (e) { + onError(e); + } + } + if (!storage) + return data; + const rawInit = toValue(defaults2); + const type = guessSerializerType(rawInit); + const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type]; + const { pause: pauseWatch, resume: resumeWatch } = watchPausable( + data, + () => write(data.value), + { flush, deep, eventFilter } + ); + watch(keyComputed, () => update(), { flush }); + if (window2 && listenToStorageChanges) { + tryOnMounted(() => { + if (storage instanceof Storage) + useEventListener(window2, "storage", update, { passive: true }); + else + useEventListener(window2, customStorageEventName, updateFromCustomEvent); + if (initOnMounted) + update(); + }); + } + if (!initOnMounted) + update(); + function dispatchWriteEvent(oldValue, newValue) { + if (window2) { + const payload = { + key: keyComputed.value, + oldValue, + newValue, + storageArea: storage + }; + window2.dispatchEvent(storage instanceof Storage ? new StorageEvent("storage", payload) : new CustomEvent(customStorageEventName, { + detail: payload + })); + } + } + function write(v) { + try { + const oldValue = storage.getItem(keyComputed.value); + if (v == null) { + dispatchWriteEvent(oldValue, null); + storage.removeItem(keyComputed.value); + } else { + const serialized = serializer.write(v); + if (oldValue !== serialized) { + storage.setItem(keyComputed.value, serialized); + dispatchWriteEvent(oldValue, serialized); + } + } + } catch (e) { + onError(e); + } + } + function read(event) { + const rawValue = event ? event.newValue : storage.getItem(keyComputed.value); + if (rawValue == null) { + if (writeDefaults && rawInit != null) + storage.setItem(keyComputed.value, serializer.write(rawInit)); + return rawInit; + } else if (!event && mergeDefaults) { + const value = serializer.read(rawValue); + if (typeof mergeDefaults === "function") + return mergeDefaults(value, rawInit); + else if (type === "object" && !Array.isArray(value)) + return { ...rawInit, ...value }; + return value; + } else if (typeof rawValue !== "string") { + return rawValue; + } else { + return serializer.read(rawValue); + } + } + function update(event) { + if (event && event.storageArea !== storage) + return; + if (event && event.key == null) { + data.value = rawInit; + return; + } + if (event && event.key !== keyComputed.value) + return; + pauseWatch(); + try { + if ((event == null ? void 0 : event.newValue) !== serializer.write(data.value)) + data.value = read(event); + } catch (e) { + onError(e); + } finally { + if (event) + nextTick(resumeWatch); + else + resumeWatch(); + } + } + function updateFromCustomEvent(event) { + update(event.detail); + } + return data; +} +var CSS_DISABLE_TRANS = "*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}"; +function useColorMode(options = {}) { + const { + selector = "html", + attribute = "class", + initialValue = "auto", + window: window2 = defaultWindow, + storage, + storageKey = "vueuse-color-scheme", + listenToStorageChanges = true, + storageRef, + emitAuto, + disableTransition = true + } = options; + const modes = { + auto: "", + light: "light", + dark: "dark", + ...options.modes || {} + }; + const preferredDark = usePreferredDark({ window: window2 }); + const system = computed(() => preferredDark.value ? "dark" : "light"); + const store = storageRef || (storageKey == null ? toRef2(initialValue) : useStorage(storageKey, initialValue, storage, { window: window2, listenToStorageChanges })); + const state = computed(() => store.value === "auto" ? system.value : store.value); + const updateHTMLAttrs = getSSRHandler( + "updateHTMLAttrs", + (selector2, attribute2, value) => { + const el = typeof selector2 === "string" ? window2 == null ? void 0 : window2.document.querySelector(selector2) : unrefElement(selector2); + if (!el) + return; + const classesToAdd = /* @__PURE__ */ new Set(); + const classesToRemove = /* @__PURE__ */ new Set(); + let attributeToChange = null; + if (attribute2 === "class") { + const current = value.split(/\s/g); + Object.values(modes).flatMap((i) => (i || "").split(/\s/g)).filter(Boolean).forEach((v) => { + if (current.includes(v)) + classesToAdd.add(v); + else + classesToRemove.add(v); + }); + } else { + attributeToChange = { key: attribute2, value }; + } + if (classesToAdd.size === 0 && classesToRemove.size === 0 && attributeToChange === null) + return; + let style; + if (disableTransition) { + style = window2.document.createElement("style"); + style.appendChild(document.createTextNode(CSS_DISABLE_TRANS)); + window2.document.head.appendChild(style); + } + for (const c of classesToAdd) { + el.classList.add(c); + } + for (const c of classesToRemove) { + el.classList.remove(c); + } + if (attributeToChange) { + el.setAttribute(attributeToChange.key, attributeToChange.value); + } + if (disableTransition) { + window2.getComputedStyle(style).opacity; + document.head.removeChild(style); + } + } + ); + function defaultOnChanged(mode) { + var _a; + updateHTMLAttrs(selector, attribute, (_a = modes[mode]) != null ? _a : mode); + } + function onChanged(mode) { + if (options.onChanged) + options.onChanged(mode, defaultOnChanged); + else + defaultOnChanged(mode); + } + watch(state, onChanged, { flush: "post", immediate: true }); + tryOnMounted(() => onChanged(state.value)); + const auto = computed({ + get() { + return emitAuto ? store.value : state.value; + }, + set(v) { + store.value = v; + } + }); + return Object.assign(auto, { store, system, state }); +} +function useConfirmDialog(revealed = shallowRef(false)) { + const confirmHook = createEventHook(); + const cancelHook = createEventHook(); + const revealHook = createEventHook(); + let _resolve = noop; + const reveal = (data) => { + revealHook.trigger(data); + revealed.value = true; + return new Promise((resolve) => { + _resolve = resolve; + }); + }; + const confirm = (data) => { + revealed.value = false; + confirmHook.trigger(data); + _resolve({ data, isCanceled: false }); + }; + const cancel = (data) => { + revealed.value = false; + cancelHook.trigger(data); + _resolve({ data, isCanceled: true }); + }; + return { + isRevealed: computed(() => revealed.value), + reveal, + confirm, + cancel, + onReveal: revealHook.on, + onConfirm: confirmHook.on, + onCancel: cancelHook.on + }; +} +function useCountdown(initialCountdown, options) { + var _a, _b; + const remaining = shallowRef(toValue(initialCountdown)); + const intervalController = useIntervalFn(() => { + var _a2, _b2; + const value = remaining.value - 1; + remaining.value = value < 0 ? 0 : value; + (_a2 = options == null ? void 0 : options.onTick) == null ? void 0 : _a2.call(options); + if (remaining.value <= 0) { + intervalController.pause(); + (_b2 = options == null ? void 0 : options.onComplete) == null ? void 0 : _b2.call(options); + } + }, (_a = options == null ? void 0 : options.interval) != null ? _a : 1e3, { immediate: (_b = options == null ? void 0 : options.immediate) != null ? _b : false }); + const reset = (countdown) => { + var _a2; + remaining.value = (_a2 = toValue(countdown)) != null ? _a2 : toValue(initialCountdown); + }; + const stop = () => { + intervalController.pause(); + reset(); + }; + const resume = () => { + if (!intervalController.isActive.value) { + if (remaining.value > 0) { + intervalController.resume(); + } + } + }; + const start = (countdown) => { + reset(countdown); + intervalController.resume(); + }; + return { + remaining, + reset, + stop, + start, + pause: intervalController.pause, + resume, + isActive: intervalController.isActive + }; +} +function useCssVar(prop, target, options = {}) { + const { window: window2 = defaultWindow, initialValue, observe = false } = options; + const variable = shallowRef(initialValue); + const elRef = computed(() => { + var _a; + return unrefElement(target) || ((_a = window2 == null ? void 0 : window2.document) == null ? void 0 : _a.documentElement); + }); + function updateCssVar() { + var _a; + const key = toValue(prop); + const el = toValue(elRef); + if (el && window2 && key) { + const value = (_a = window2.getComputedStyle(el).getPropertyValue(key)) == null ? void 0 : _a.trim(); + variable.value = value || variable.value || initialValue; + } + } + if (observe) { + useMutationObserver(elRef, updateCssVar, { + attributeFilter: ["style", "class"], + window: window2 + }); + } + watch( + [elRef, () => toValue(prop)], + (_, old) => { + if (old[0] && old[1]) + old[0].style.removeProperty(old[1]); + updateCssVar(); + }, + { immediate: true } + ); + watch( + [variable, elRef], + ([val, el]) => { + const raw_prop = toValue(prop); + if ((el == null ? void 0 : el.style) && raw_prop) { + if (val == null) + el.style.removeProperty(raw_prop); + else + el.style.setProperty(raw_prop, val); + } + }, + { immediate: true } + ); + return variable; +} +function useCurrentElement(rootComponent) { + const vm = getCurrentInstance(); + const currentElement = computedWithControl( + () => null, + () => rootComponent ? unrefElement(rootComponent) : vm.proxy.$el + ); + onUpdated(currentElement.trigger); + onMounted(currentElement.trigger); + return currentElement; +} +function useCycleList(list, options) { + const state = shallowRef(getInitialValue()); + const listRef = toRef2(list); + const index = computed({ + get() { + var _a; + const targetList = listRef.value; + let index2 = (options == null ? void 0 : options.getIndexOf) ? options.getIndexOf(state.value, targetList) : targetList.indexOf(state.value); + if (index2 < 0) + index2 = (_a = options == null ? void 0 : options.fallbackIndex) != null ? _a : 0; + return index2; + }, + set(v) { + set2(v); + } + }); + function set2(i) { + const targetList = listRef.value; + const length = targetList.length; + const index2 = (i % length + length) % length; + const value = targetList[index2]; + state.value = value; + return value; + } + function shift(delta = 1) { + return set2(index.value + delta); + } + function next(n = 1) { + return shift(n); + } + function prev(n = 1) { + return shift(-n); + } + function getInitialValue() { + var _a, _b; + return (_b = toValue((_a = options == null ? void 0 : options.initialValue) != null ? _a : toValue(list)[0])) != null ? _b : void 0; + } + watch(listRef, () => set2(index.value)); + return { + state, + index, + next, + prev, + go: set2 + }; +} +function useDark(options = {}) { + const { + valueDark = "dark", + valueLight = "" + } = options; + const mode = useColorMode({ + ...options, + onChanged: (mode2, defaultHandler) => { + var _a; + if (options.onChanged) + (_a = options.onChanged) == null ? void 0 : _a.call(options, mode2 === "dark", defaultHandler, mode2); + else + defaultHandler(mode2); + }, + modes: { + dark: valueDark, + light: valueLight + } + }); + const system = computed(() => mode.system.value); + const isDark = computed({ + get() { + return mode.value === "dark"; + }, + set(v) { + const modeVal = v ? "dark" : "light"; + if (system.value === modeVal) + mode.value = "auto"; + else + mode.value = modeVal; + } + }); + return isDark; +} +function fnBypass(v) { + return v; +} +function fnSetSource(source, value) { + return source.value = value; +} +function defaultDump(clone) { + return clone ? typeof clone === "function" ? clone : cloneFnJSON : fnBypass; +} +function defaultParse(clone) { + return clone ? typeof clone === "function" ? clone : cloneFnJSON : fnBypass; +} +function useManualRefHistory(source, options = {}) { + const { + clone = false, + dump = defaultDump(clone), + parse = defaultParse(clone), + setSource = fnSetSource + } = options; + function _createHistoryRecord() { + return markRaw({ + snapshot: dump(source.value), + timestamp: timestamp() + }); + } + const last = ref(_createHistoryRecord()); + const undoStack = ref([]); + const redoStack = ref([]); + const _setSource = (record) => { + setSource(source, parse(record.snapshot)); + last.value = record; + }; + const commit = () => { + undoStack.value.unshift(last.value); + last.value = _createHistoryRecord(); + if (options.capacity && undoStack.value.length > options.capacity) + undoStack.value.splice(options.capacity, Number.POSITIVE_INFINITY); + if (redoStack.value.length) + redoStack.value.splice(0, redoStack.value.length); + }; + const clear = () => { + undoStack.value.splice(0, undoStack.value.length); + redoStack.value.splice(0, redoStack.value.length); + }; + const undo = () => { + const state = undoStack.value.shift(); + if (state) { + redoStack.value.unshift(last.value); + _setSource(state); + } + }; + const redo = () => { + const state = redoStack.value.shift(); + if (state) { + undoStack.value.unshift(last.value); + _setSource(state); + } + }; + const reset = () => { + _setSource(last.value); + }; + const history = computed(() => [last.value, ...undoStack.value]); + const canUndo = computed(() => undoStack.value.length > 0); + const canRedo = computed(() => redoStack.value.length > 0); + return { + source, + undoStack, + redoStack, + last, + history, + canUndo, + canRedo, + clear, + commit, + reset, + undo, + redo + }; +} +function useRefHistory(source, options = {}) { + const { + deep = false, + flush = "pre", + eventFilter + } = options; + const { + eventFilter: composedFilter, + pause, + resume: resumeTracking, + isActive: isTracking + } = pausableFilter(eventFilter); + const { + ignoreUpdates, + ignorePrevAsyncUpdates, + stop + } = watchIgnorable( + source, + commit, + { deep, flush, eventFilter: composedFilter } + ); + function setSource(source2, value) { + ignorePrevAsyncUpdates(); + ignoreUpdates(() => { + source2.value = value; + }); + } + const manualHistory = useManualRefHistory(source, { ...options, clone: options.clone || deep, setSource }); + const { clear, commit: manualCommit } = manualHistory; + function commit() { + ignorePrevAsyncUpdates(); + manualCommit(); + } + function resume(commitNow) { + resumeTracking(); + if (commitNow) + commit(); + } + function batch(fn) { + let canceled = false; + const cancel = () => canceled = true; + ignoreUpdates(() => { + fn(cancel); + }); + if (!canceled) + commit(); + } + function dispose() { + stop(); + clear(); + } + return { + ...manualHistory, + isTracking, + pause, + resume, + commit, + batch, + dispose + }; +} +function useDebouncedRefHistory(source, options = {}) { + const filter = options.debounce ? debounceFilter(options.debounce) : void 0; + const history = useRefHistory(source, { ...options, eventFilter: filter }); + return { + ...history + }; +} +function useDeviceMotion(options = {}) { + const { + window: window2 = defaultWindow, + requestPermissions = false, + eventFilter = bypassFilter + } = options; + const isSupported = useSupported(() => typeof DeviceMotionEvent !== "undefined"); + const requirePermissions = useSupported(() => isSupported.value && "requestPermission" in DeviceMotionEvent && typeof DeviceMotionEvent.requestPermission === "function"); + const permissionGranted = shallowRef(false); + const acceleration = ref({ x: null, y: null, z: null }); + const rotationRate = ref({ alpha: null, beta: null, gamma: null }); + const interval = shallowRef(0); + const accelerationIncludingGravity = ref({ + x: null, + y: null, + z: null + }); + function init() { + if (window2) { + const onDeviceMotion = createFilterWrapper( + eventFilter, + (event) => { + var _a, _b, _c, _d, _e, _f, _g, _h, _i; + acceleration.value = { + x: ((_a = event.acceleration) == null ? void 0 : _a.x) || null, + y: ((_b = event.acceleration) == null ? void 0 : _b.y) || null, + z: ((_c = event.acceleration) == null ? void 0 : _c.z) || null + }; + accelerationIncludingGravity.value = { + x: ((_d = event.accelerationIncludingGravity) == null ? void 0 : _d.x) || null, + y: ((_e = event.accelerationIncludingGravity) == null ? void 0 : _e.y) || null, + z: ((_f = event.accelerationIncludingGravity) == null ? void 0 : _f.z) || null + }; + rotationRate.value = { + alpha: ((_g = event.rotationRate) == null ? void 0 : _g.alpha) || null, + beta: ((_h = event.rotationRate) == null ? void 0 : _h.beta) || null, + gamma: ((_i = event.rotationRate) == null ? void 0 : _i.gamma) || null + }; + interval.value = event.interval; + } + ); + useEventListener(window2, "devicemotion", onDeviceMotion, { passive: true }); + } + } + const ensurePermissions = async () => { + if (!requirePermissions.value) + permissionGranted.value = true; + if (permissionGranted.value) + return; + if (requirePermissions.value) { + const requestPermission = DeviceMotionEvent.requestPermission; + try { + const response = await requestPermission(); + if (response === "granted") { + permissionGranted.value = true; + init(); + } + } catch (error) { + console.error(error); + } + } + }; + if (isSupported.value) { + if (requestPermissions && requirePermissions.value) { + ensurePermissions().then(() => init()); + } else { + init(); + } + } + return { + acceleration, + accelerationIncludingGravity, + rotationRate, + interval, + isSupported, + requirePermissions, + ensurePermissions, + permissionGranted + }; +} +function useDeviceOrientation(options = {}) { + const { window: window2 = defaultWindow } = options; + const isSupported = useSupported(() => window2 && "DeviceOrientationEvent" in window2); + const isAbsolute = shallowRef(false); + const alpha = shallowRef(null); + const beta = shallowRef(null); + const gamma = shallowRef(null); + if (window2 && isSupported.value) { + useEventListener(window2, "deviceorientation", (event) => { + isAbsolute.value = event.absolute; + alpha.value = event.alpha; + beta.value = event.beta; + gamma.value = event.gamma; + }, { passive: true }); + } + return { + isSupported, + isAbsolute, + alpha, + beta, + gamma + }; +} +function useDevicePixelRatio(options = {}) { + const { + window: window2 = defaultWindow + } = options; + const pixelRatio = shallowRef(1); + const query = useMediaQuery(() => `(resolution: ${pixelRatio.value}dppx)`, options); + let stop = noop; + if (window2) { + stop = watchImmediate(query, () => pixelRatio.value = window2.devicePixelRatio); + } + return { + pixelRatio: readonly(pixelRatio), + stop + }; +} +function useDevicesList(options = {}) { + const { + navigator: navigator2 = defaultNavigator, + requestPermissions = false, + constraints = { audio: true, video: true }, + onUpdated: onUpdated2 + } = options; + const devices = ref([]); + const videoInputs = computed(() => devices.value.filter((i) => i.kind === "videoinput")); + const audioInputs = computed(() => devices.value.filter((i) => i.kind === "audioinput")); + const audioOutputs = computed(() => devices.value.filter((i) => i.kind === "audiooutput")); + const isSupported = useSupported(() => navigator2 && navigator2.mediaDevices && navigator2.mediaDevices.enumerateDevices); + const permissionGranted = shallowRef(false); + let stream; + async function update() { + if (!isSupported.value) + return; + devices.value = await navigator2.mediaDevices.enumerateDevices(); + onUpdated2 == null ? void 0 : onUpdated2(devices.value); + if (stream) { + stream.getTracks().forEach((t) => t.stop()); + stream = null; + } + } + async function ensurePermissions() { + const deviceName = constraints.video ? "camera" : "microphone"; + if (!isSupported.value) + return false; + if (permissionGranted.value) + return true; + const { state, query } = usePermission(deviceName, { controls: true }); + await query(); + if (state.value !== "granted") { + let granted = true; + try { + stream = await navigator2.mediaDevices.getUserMedia(constraints); + } catch (e) { + stream = null; + granted = false; + } + update(); + permissionGranted.value = granted; + } else { + permissionGranted.value = true; + } + return permissionGranted.value; + } + if (isSupported.value) { + if (requestPermissions) + ensurePermissions(); + useEventListener(navigator2.mediaDevices, "devicechange", update, { passive: true }); + update(); + } + return { + devices, + ensurePermissions, + permissionGranted, + videoInputs, + audioInputs, + audioOutputs, + isSupported + }; +} +function useDisplayMedia(options = {}) { + var _a; + const enabled = shallowRef((_a = options.enabled) != null ? _a : false); + const video = options.video; + const audio = options.audio; + const { navigator: navigator2 = defaultNavigator } = options; + const isSupported = useSupported(() => { + var _a2; + return (_a2 = navigator2 == null ? void 0 : navigator2.mediaDevices) == null ? void 0 : _a2.getDisplayMedia; + }); + const constraint = { audio, video }; + const stream = shallowRef(); + async function _start() { + var _a2; + if (!isSupported.value || stream.value) + return; + stream.value = await navigator2.mediaDevices.getDisplayMedia(constraint); + (_a2 = stream.value) == null ? void 0 : _a2.getTracks().forEach((t) => useEventListener(t, "ended", stop, { passive: true })); + return stream.value; + } + async function _stop() { + var _a2; + (_a2 = stream.value) == null ? void 0 : _a2.getTracks().forEach((t) => t.stop()); + stream.value = void 0; + } + function stop() { + _stop(); + enabled.value = false; + } + async function start() { + await _start(); + if (stream.value) + enabled.value = true; + return stream.value; + } + watch( + enabled, + (v) => { + if (v) + _start(); + else + _stop(); + }, + { immediate: true } + ); + return { + isSupported, + stream, + start, + stop, + enabled + }; +} +function useDocumentVisibility(options = {}) { + const { document: document2 = defaultDocument } = options; + if (!document2) + return shallowRef("visible"); + const visibility = shallowRef(document2.visibilityState); + useEventListener(document2, "visibilitychange", () => { + visibility.value = document2.visibilityState; + }, { passive: true }); + return visibility; +} +function useDraggable(target, options = {}) { + var _a; + const { + pointerTypes, + preventDefault: preventDefault2, + stopPropagation, + exact, + onMove, + onEnd, + onStart, + initialValue, + axis = "both", + draggingElement = defaultWindow, + containerElement, + handle: draggingHandle = target, + buttons = [0] + } = options; + const position = ref( + (_a = toValue(initialValue)) != null ? _a : { x: 0, y: 0 } + ); + const pressedDelta = ref(); + const filterEvent = (e) => { + if (pointerTypes) + return pointerTypes.includes(e.pointerType); + return true; + }; + const handleEvent = (e) => { + if (toValue(preventDefault2)) + e.preventDefault(); + if (toValue(stopPropagation)) + e.stopPropagation(); + }; + const start = (e) => { + var _a2; + if (!toValue(buttons).includes(e.button)) + return; + if (toValue(options.disabled) || !filterEvent(e)) + return; + if (toValue(exact) && e.target !== toValue(target)) + return; + const container = toValue(containerElement); + const containerRect = (_a2 = container == null ? void 0 : container.getBoundingClientRect) == null ? void 0 : _a2.call(container); + const targetRect = toValue(target).getBoundingClientRect(); + const pos = { + x: e.clientX - (container ? targetRect.left - containerRect.left + container.scrollLeft : targetRect.left), + y: e.clientY - (container ? targetRect.top - containerRect.top + container.scrollTop : targetRect.top) + }; + if ((onStart == null ? void 0 : onStart(pos, e)) === false) + return; + pressedDelta.value = pos; + handleEvent(e); + }; + const move = (e) => { + if (toValue(options.disabled) || !filterEvent(e)) + return; + if (!pressedDelta.value) + return; + const container = toValue(containerElement); + const targetRect = toValue(target).getBoundingClientRect(); + let { x, y } = position.value; + if (axis === "x" || axis === "both") { + x = e.clientX - pressedDelta.value.x; + if (container) + x = Math.min(Math.max(0, x), container.scrollWidth - targetRect.width); + } + if (axis === "y" || axis === "both") { + y = e.clientY - pressedDelta.value.y; + if (container) + y = Math.min(Math.max(0, y), container.scrollHeight - targetRect.height); + } + position.value = { + x, + y + }; + onMove == null ? void 0 : onMove(position.value, e); + handleEvent(e); + }; + const end = (e) => { + if (toValue(options.disabled) || !filterEvent(e)) + return; + if (!pressedDelta.value) + return; + pressedDelta.value = void 0; + onEnd == null ? void 0 : onEnd(position.value, e); + handleEvent(e); + }; + if (isClient) { + const config = () => { + var _a2; + return { + capture: (_a2 = options.capture) != null ? _a2 : true, + passive: !toValue(preventDefault2) + }; + }; + useEventListener(draggingHandle, "pointerdown", start, config); + useEventListener(draggingElement, "pointermove", move, config); + useEventListener(draggingElement, "pointerup", end, config); + } + return { + ...toRefs2(position), + position, + isDragging: computed(() => !!pressedDelta.value), + style: computed( + () => `left:${position.value.x}px;top:${position.value.y}px;` + ) + }; +} +function useDropZone(target, options = {}) { + var _a, _b; + const isOverDropZone = shallowRef(false); + const files = shallowRef(null); + let counter = 0; + let isValid = true; + if (isClient) { + const _options = typeof options === "function" ? { onDrop: options } : options; + const multiple = (_a = _options.multiple) != null ? _a : true; + const preventDefaultForUnhandled = (_b = _options.preventDefaultForUnhandled) != null ? _b : false; + const getFiles = (event) => { + var _a2, _b2; + const list = Array.from((_b2 = (_a2 = event.dataTransfer) == null ? void 0 : _a2.files) != null ? _b2 : []); + return list.length === 0 ? null : multiple ? list : [list[0]]; + }; + const checkDataTypes = (types) => { + const dataTypes = unref(_options.dataTypes); + if (typeof dataTypes === "function") + return dataTypes(types); + if (!(dataTypes == null ? void 0 : dataTypes.length)) + return true; + if (types.length === 0) + return false; + return types.every( + (type) => dataTypes.some((allowedType) => type.includes(allowedType)) + ); + }; + const checkValidity = (items) => { + const types = Array.from(items != null ? items : []).map((item) => item.type); + const dataTypesValid = checkDataTypes(types); + const multipleFilesValid = multiple || items.length <= 1; + return dataTypesValid && multipleFilesValid; + }; + const isSafari = () => /^(?:(?!chrome|android).)*safari/i.test(navigator.userAgent) && !("chrome" in window); + const handleDragEvent = (event, eventType) => { + var _a2, _b2, _c, _d, _e, _f; + const dataTransferItemList = (_a2 = event.dataTransfer) == null ? void 0 : _a2.items; + isValid = (_b2 = dataTransferItemList && checkValidity(dataTransferItemList)) != null ? _b2 : false; + if (preventDefaultForUnhandled) { + event.preventDefault(); + } + if (!isSafari() && !isValid) { + if (event.dataTransfer) { + event.dataTransfer.dropEffect = "none"; + } + return; + } + event.preventDefault(); + if (event.dataTransfer) { + event.dataTransfer.dropEffect = "copy"; + } + const currentFiles = getFiles(event); + switch (eventType) { + case "enter": + counter += 1; + isOverDropZone.value = true; + (_c = _options.onEnter) == null ? void 0 : _c.call(_options, null, event); + break; + case "over": + (_d = _options.onOver) == null ? void 0 : _d.call(_options, null, event); + break; + case "leave": + counter -= 1; + if (counter === 0) + isOverDropZone.value = false; + (_e = _options.onLeave) == null ? void 0 : _e.call(_options, null, event); + break; + case "drop": + counter = 0; + isOverDropZone.value = false; + if (isValid) { + files.value = currentFiles; + (_f = _options.onDrop) == null ? void 0 : _f.call(_options, currentFiles, event); + } + break; + } + }; + useEventListener(target, "dragenter", (event) => handleDragEvent(event, "enter")); + useEventListener(target, "dragover", (event) => handleDragEvent(event, "over")); + useEventListener(target, "dragleave", (event) => handleDragEvent(event, "leave")); + useEventListener(target, "drop", (event) => handleDragEvent(event, "drop")); + } + return { + files, + isOverDropZone + }; +} +function useResizeObserver(target, callback, options = {}) { + const { window: window2 = defaultWindow, ...observerOptions } = options; + let observer; + const isSupported = useSupported(() => window2 && "ResizeObserver" in window2); + const cleanup = () => { + if (observer) { + observer.disconnect(); + observer = void 0; + } + }; + const targets = computed(() => { + const _targets = toValue(target); + return Array.isArray(_targets) ? _targets.map((el) => unrefElement(el)) : [unrefElement(_targets)]; + }); + const stopWatch = watch( + targets, + (els) => { + cleanup(); + if (isSupported.value && window2) { + observer = new ResizeObserver(callback); + for (const _el of els) { + if (_el) + observer.observe(_el, observerOptions); + } + } + }, + { immediate: true, flush: "post" } + ); + const stop = () => { + cleanup(); + stopWatch(); + }; + tryOnScopeDispose(stop); + return { + isSupported, + stop + }; +} +function useElementBounding(target, options = {}) { + const { + reset = true, + windowResize = true, + windowScroll = true, + immediate = true, + updateTiming = "sync" + } = options; + const height = shallowRef(0); + const bottom = shallowRef(0); + const left = shallowRef(0); + const right = shallowRef(0); + const top = shallowRef(0); + const width = shallowRef(0); + const x = shallowRef(0); + const y = shallowRef(0); + function recalculate() { + const el = unrefElement(target); + if (!el) { + if (reset) { + height.value = 0; + bottom.value = 0; + left.value = 0; + right.value = 0; + top.value = 0; + width.value = 0; + x.value = 0; + y.value = 0; + } + return; + } + const rect = el.getBoundingClientRect(); + height.value = rect.height; + bottom.value = rect.bottom; + left.value = rect.left; + right.value = rect.right; + top.value = rect.top; + width.value = rect.width; + x.value = rect.x; + y.value = rect.y; + } + function update() { + if (updateTiming === "sync") + recalculate(); + else if (updateTiming === "next-frame") + requestAnimationFrame(() => recalculate()); + } + useResizeObserver(target, update); + watch(() => unrefElement(target), (ele) => !ele && update()); + useMutationObserver(target, update, { + attributeFilter: ["style", "class"] + }); + if (windowScroll) + useEventListener("scroll", update, { capture: true, passive: true }); + if (windowResize) + useEventListener("resize", update, { passive: true }); + tryOnMounted(() => { + if (immediate) + update(); + }); + return { + height, + bottom, + left, + right, + top, + width, + x, + y, + update + }; +} +function useElementByPoint(options) { + const { + x, + y, + document: document2 = defaultDocument, + multiple, + interval = "requestAnimationFrame", + immediate = true + } = options; + const isSupported = useSupported(() => { + if (toValue(multiple)) + return document2 && "elementsFromPoint" in document2; + return document2 && "elementFromPoint" in document2; + }); + const element = shallowRef(null); + const cb = () => { + var _a, _b; + element.value = toValue(multiple) ? (_a = document2 == null ? void 0 : document2.elementsFromPoint(toValue(x), toValue(y))) != null ? _a : [] : (_b = document2 == null ? void 0 : document2.elementFromPoint(toValue(x), toValue(y))) != null ? _b : null; + }; + const controls = interval === "requestAnimationFrame" ? useRafFn(cb, { immediate }) : useIntervalFn(cb, interval, { immediate }); + return { + isSupported, + element, + ...controls + }; +} +function useElementHover(el, options = {}) { + const { + delayEnter = 0, + delayLeave = 0, + triggerOnRemoval = false, + window: window2 = defaultWindow + } = options; + const isHovered = shallowRef(false); + let timer; + const toggle = (entering) => { + const delay = entering ? delayEnter : delayLeave; + if (timer) { + clearTimeout(timer); + timer = void 0; + } + if (delay) + timer = setTimeout(() => isHovered.value = entering, delay); + else + isHovered.value = entering; + }; + if (!window2) + return isHovered; + useEventListener(el, "mouseenter", () => toggle(true), { passive: true }); + useEventListener(el, "mouseleave", () => toggle(false), { passive: true }); + if (triggerOnRemoval) { + onElementRemoval( + computed(() => unrefElement(el)), + () => toggle(false) + ); + } + return isHovered; +} +function useElementSize(target, initialSize = { width: 0, height: 0 }, options = {}) { + const { window: window2 = defaultWindow, box = "content-box" } = options; + const isSVG = computed(() => { + var _a, _b; + return (_b = (_a = unrefElement(target)) == null ? void 0 : _a.namespaceURI) == null ? void 0 : _b.includes("svg"); + }); + const width = shallowRef(initialSize.width); + const height = shallowRef(initialSize.height); + const { stop: stop1 } = useResizeObserver( + target, + ([entry]) => { + const boxSize = box === "border-box" ? entry.borderBoxSize : box === "content-box" ? entry.contentBoxSize : entry.devicePixelContentBoxSize; + if (window2 && isSVG.value) { + const $elem = unrefElement(target); + if ($elem) { + const rect = $elem.getBoundingClientRect(); + width.value = rect.width; + height.value = rect.height; + } + } else { + if (boxSize) { + const formatBoxSize = toArray(boxSize); + width.value = formatBoxSize.reduce((acc, { inlineSize }) => acc + inlineSize, 0); + height.value = formatBoxSize.reduce((acc, { blockSize }) => acc + blockSize, 0); + } else { + width.value = entry.contentRect.width; + height.value = entry.contentRect.height; + } + } + }, + options + ); + tryOnMounted(() => { + const ele = unrefElement(target); + if (ele) { + width.value = "offsetWidth" in ele ? ele.offsetWidth : initialSize.width; + height.value = "offsetHeight" in ele ? ele.offsetHeight : initialSize.height; + } + }); + const stop2 = watch( + () => unrefElement(target), + (ele) => { + width.value = ele ? initialSize.width : 0; + height.value = ele ? initialSize.height : 0; + } + ); + function stop() { + stop1(); + stop2(); + } + return { + width, + height, + stop + }; +} +function useIntersectionObserver(target, callback, options = {}) { + const { + root, + rootMargin = "0px", + threshold = 0, + window: window2 = defaultWindow, + immediate = true + } = options; + const isSupported = useSupported(() => window2 && "IntersectionObserver" in window2); + const targets = computed(() => { + const _target = toValue(target); + return toArray(_target).map(unrefElement).filter(notNullish); + }); + let cleanup = noop; + const isActive = shallowRef(immediate); + const stopWatch = isSupported.value ? watch( + () => [targets.value, unrefElement(root), isActive.value], + ([targets2, root2]) => { + cleanup(); + if (!isActive.value) + return; + if (!targets2.length) + return; + const observer = new IntersectionObserver( + callback, + { + root: unrefElement(root2), + rootMargin, + threshold + } + ); + targets2.forEach((el) => el && observer.observe(el)); + cleanup = () => { + observer.disconnect(); + cleanup = noop; + }; + }, + { immediate, flush: "post" } + ) : noop; + const stop = () => { + cleanup(); + stopWatch(); + isActive.value = false; + }; + tryOnScopeDispose(stop); + return { + isSupported, + isActive, + pause() { + cleanup(); + isActive.value = false; + }, + resume() { + isActive.value = true; + }, + stop + }; +} +function useElementVisibility(element, options = {}) { + const { + window: window2 = defaultWindow, + scrollTarget, + threshold = 0, + rootMargin, + once = false + } = options; + const elementIsVisible = shallowRef(false); + const { stop } = useIntersectionObserver( + element, + (intersectionObserverEntries) => { + let isIntersecting = elementIsVisible.value; + let latestTime = 0; + for (const entry of intersectionObserverEntries) { + if (entry.time >= latestTime) { + latestTime = entry.time; + isIntersecting = entry.isIntersecting; + } + } + elementIsVisible.value = isIntersecting; + if (once) { + watchOnce(elementIsVisible, () => { + stop(); + }); + } + }, + { + root: scrollTarget, + window: window2, + threshold, + rootMargin: toValue(rootMargin) + } + ); + return elementIsVisible; +} +var events = /* @__PURE__ */ new Map(); +function useEventBus(key) { + const scope = getCurrentScope(); + function on(listener) { + var _a; + const listeners = events.get(key) || /* @__PURE__ */ new Set(); + listeners.add(listener); + events.set(key, listeners); + const _off = () => off(listener); + (_a = scope == null ? void 0 : scope.cleanups) == null ? void 0 : _a.push(_off); + return _off; + } + function once(listener) { + function _listener(...args) { + off(_listener); + listener(...args); + } + return on(_listener); + } + function off(listener) { + const listeners = events.get(key); + if (!listeners) + return; + listeners.delete(listener); + if (!listeners.size) + reset(); + } + function reset() { + events.delete(key); + } + function emit(event, payload) { + var _a; + (_a = events.get(key)) == null ? void 0 : _a.forEach((v) => v(event, payload)); + } + return { on, once, off, emit, reset }; +} +function resolveNestedOptions$1(options) { + if (options === true) + return {}; + return options; +} +function useEventSource(url, events2 = [], options = {}) { + const event = shallowRef(null); + const data = shallowRef(null); + const status = shallowRef("CONNECTING"); + const eventSource = ref(null); + const error = shallowRef(null); + const urlRef = toRef2(url); + const lastEventId = shallowRef(null); + let explicitlyClosed = false; + let retried = 0; + const { + withCredentials = false, + immediate = true, + autoConnect = true, + autoReconnect + } = options; + const close = () => { + if (isClient && eventSource.value) { + eventSource.value.close(); + eventSource.value = null; + status.value = "CLOSED"; + explicitlyClosed = true; + } + }; + const _init = () => { + if (explicitlyClosed || typeof urlRef.value === "undefined") + return; + const es = new EventSource(urlRef.value, { withCredentials }); + status.value = "CONNECTING"; + eventSource.value = es; + es.onopen = () => { + status.value = "OPEN"; + error.value = null; + }; + es.onerror = (e) => { + status.value = "CLOSED"; + error.value = e; + if (es.readyState === 2 && !explicitlyClosed && autoReconnect) { + es.close(); + const { + retries = -1, + delay = 1e3, + onFailed + } = resolveNestedOptions$1(autoReconnect); + retried += 1; + if (typeof retries === "number" && (retries < 0 || retried < retries)) + setTimeout(_init, delay); + else if (typeof retries === "function" && retries()) + setTimeout(_init, delay); + else + onFailed == null ? void 0 : onFailed(); + } + }; + es.onmessage = (e) => { + event.value = null; + data.value = e.data; + lastEventId.value = e.lastEventId; + }; + for (const event_name of events2) { + useEventListener(es, event_name, (e) => { + event.value = event_name; + data.value = e.data || null; + }, { passive: true }); + } + }; + const open = () => { + if (!isClient) + return; + close(); + explicitlyClosed = false; + retried = 0; + _init(); + }; + if (immediate) + open(); + if (autoConnect) + watch(urlRef, open); + tryOnScopeDispose(close); + return { + eventSource, + event, + data, + status, + error, + open, + close, + lastEventId + }; +} +function useEyeDropper(options = {}) { + const { initialValue = "" } = options; + const isSupported = useSupported(() => typeof window !== "undefined" && "EyeDropper" in window); + const sRGBHex = shallowRef(initialValue); + async function open(openOptions) { + if (!isSupported.value) + return; + const eyeDropper = new window.EyeDropper(); + const result = await eyeDropper.open(openOptions); + sRGBHex.value = result.sRGBHex; + return result; + } + return { isSupported, sRGBHex, open }; +} +function useFavicon(newIcon = null, options = {}) { + const { + baseUrl = "", + rel = "icon", + document: document2 = defaultDocument + } = options; + const favicon = toRef2(newIcon); + const applyIcon = (icon) => { + const elements = document2 == null ? void 0 : document2.head.querySelectorAll(`link[rel*="${rel}"]`); + if (!elements || elements.length === 0) { + const link = document2 == null ? void 0 : document2.createElement("link"); + if (link) { + link.rel = rel; + link.href = `${baseUrl}${icon}`; + link.type = `image/${icon.split(".").pop()}`; + document2 == null ? void 0 : document2.head.append(link); + } + return; + } + elements == null ? void 0 : elements.forEach((el) => el.href = `${baseUrl}${icon}`); + }; + watch( + favicon, + (i, o) => { + if (typeof i === "string" && i !== o) + applyIcon(i); + }, + { immediate: true } + ); + return favicon; +} +var payloadMapping = { + json: "application/json", + text: "text/plain" +}; +function isFetchOptions(obj) { + return obj && containsProp(obj, "immediate", "refetch", "initialData", "timeout", "beforeFetch", "afterFetch", "onFetchError", "fetch", "updateDataOnError"); +} +var reAbsolute = /^(?:[a-z][a-z\d+\-.]*:)?\/\//i; +function isAbsoluteURL(url) { + return reAbsolute.test(url); +} +function headersToObject(headers) { + if (typeof Headers !== "undefined" && headers instanceof Headers) + return Object.fromEntries(headers.entries()); + return headers; +} +function combineCallbacks(combination, ...callbacks) { + if (combination === "overwrite") { + return async (ctx) => { + let callback; + for (let i = callbacks.length - 1; i >= 0; i--) { + if (callbacks[i] != null) { + callback = callbacks[i]; + break; + } + } + if (callback) + return { ...ctx, ...await callback(ctx) }; + return ctx; + }; + } else { + return async (ctx) => { + for (const callback of callbacks) { + if (callback) + ctx = { ...ctx, ...await callback(ctx) }; + } + return ctx; + }; + } +} +function createFetch(config = {}) { + const _combination = config.combination || "chain"; + const _options = config.options || {}; + const _fetchOptions = config.fetchOptions || {}; + function useFactoryFetch(url, ...args) { + const computedUrl = computed(() => { + const baseUrl = toValue(config.baseUrl); + const targetUrl = toValue(url); + return baseUrl && !isAbsoluteURL(targetUrl) ? joinPaths(baseUrl, targetUrl) : targetUrl; + }); + let options = _options; + let fetchOptions = _fetchOptions; + if (args.length > 0) { + if (isFetchOptions(args[0])) { + options = { + ...options, + ...args[0], + beforeFetch: combineCallbacks(_combination, _options.beforeFetch, args[0].beforeFetch), + afterFetch: combineCallbacks(_combination, _options.afterFetch, args[0].afterFetch), + onFetchError: combineCallbacks(_combination, _options.onFetchError, args[0].onFetchError) + }; + } else { + fetchOptions = { + ...fetchOptions, + ...args[0], + headers: { + ...headersToObject(fetchOptions.headers) || {}, + ...headersToObject(args[0].headers) || {} + } + }; + } + } + if (args.length > 1 && isFetchOptions(args[1])) { + options = { + ...options, + ...args[1], + beforeFetch: combineCallbacks(_combination, _options.beforeFetch, args[1].beforeFetch), + afterFetch: combineCallbacks(_combination, _options.afterFetch, args[1].afterFetch), + onFetchError: combineCallbacks(_combination, _options.onFetchError, args[1].onFetchError) + }; + } + return useFetch(computedUrl, fetchOptions, options); + } + return useFactoryFetch; +} +function useFetch(url, ...args) { + var _a; + const supportsAbort = typeof AbortController === "function"; + let fetchOptions = {}; + let options = { + immediate: true, + refetch: false, + timeout: 0, + updateDataOnError: false + }; + const config = { + method: "GET", + type: "text", + payload: void 0 + }; + if (args.length > 0) { + if (isFetchOptions(args[0])) + options = { ...options, ...args[0] }; + else + fetchOptions = args[0]; + } + if (args.length > 1) { + if (isFetchOptions(args[1])) + options = { ...options, ...args[1] }; + } + const { + fetch = (_a = defaultWindow) == null ? void 0 : _a.fetch, + initialData, + timeout + } = options; + const responseEvent = createEventHook(); + const errorEvent = createEventHook(); + const finallyEvent = createEventHook(); + const isFinished = shallowRef(false); + const isFetching = shallowRef(false); + const aborted = shallowRef(false); + const statusCode = shallowRef(null); + const response = shallowRef(null); + const error = shallowRef(null); + const data = shallowRef(initialData || null); + const canAbort = computed(() => supportsAbort && isFetching.value); + let controller; + let timer; + const abort = () => { + if (supportsAbort) { + controller == null ? void 0 : controller.abort(); + controller = new AbortController(); + controller.signal.onabort = () => aborted.value = true; + fetchOptions = { + ...fetchOptions, + signal: controller.signal + }; + } + }; + const loading = (isLoading) => { + isFetching.value = isLoading; + isFinished.value = !isLoading; + }; + if (timeout) + timer = useTimeoutFn(abort, timeout, { immediate: false }); + let executeCounter = 0; + const execute = async (throwOnFailed = false) => { + var _a2, _b; + abort(); + loading(true); + error.value = null; + statusCode.value = null; + aborted.value = false; + executeCounter += 1; + const currentExecuteCounter = executeCounter; + const defaultFetchOptions = { + method: config.method, + headers: {} + }; + const payload = toValue(config.payload); + if (payload) { + const headers = headersToObject(defaultFetchOptions.headers); + const proto = Object.getPrototypeOf(payload); + if (!config.payloadType && payload && (proto === Object.prototype || Array.isArray(proto)) && !(payload instanceof FormData)) + config.payloadType = "json"; + if (config.payloadType) + headers["Content-Type"] = (_a2 = payloadMapping[config.payloadType]) != null ? _a2 : config.payloadType; + defaultFetchOptions.body = config.payloadType === "json" ? JSON.stringify(payload) : payload; + } + let isCanceled = false; + const context = { + url: toValue(url), + options: { + ...defaultFetchOptions, + ...fetchOptions + }, + cancel: () => { + isCanceled = true; + } + }; + if (options.beforeFetch) + Object.assign(context, await options.beforeFetch(context)); + if (isCanceled || !fetch) { + loading(false); + return Promise.resolve(null); + } + let responseData = null; + if (timer) + timer.start(); + return fetch( + context.url, + { + ...defaultFetchOptions, + ...context.options, + headers: { + ...headersToObject(defaultFetchOptions.headers), + ...headersToObject((_b = context.options) == null ? void 0 : _b.headers) + } + } + ).then(async (fetchResponse) => { + response.value = fetchResponse; + statusCode.value = fetchResponse.status; + responseData = await fetchResponse.clone()[config.type](); + if (!fetchResponse.ok) { + data.value = initialData || null; + throw new Error(fetchResponse.statusText); + } + if (options.afterFetch) { + ({ data: responseData } = await options.afterFetch({ + data: responseData, + response: fetchResponse, + context, + execute + })); + } + data.value = responseData; + responseEvent.trigger(fetchResponse); + return fetchResponse; + }).catch(async (fetchError) => { + let errorData = fetchError.message || fetchError.name; + if (options.onFetchError) { + ({ error: errorData, data: responseData } = await options.onFetchError({ + data: responseData, + error: fetchError, + response: response.value, + context, + execute + })); + } + error.value = errorData; + if (options.updateDataOnError) + data.value = responseData; + errorEvent.trigger(fetchError); + if (throwOnFailed) + throw fetchError; + return null; + }).finally(() => { + if (currentExecuteCounter === executeCounter) + loading(false); + if (timer) + timer.stop(); + finallyEvent.trigger(null); + }); + }; + const refetch = toRef2(options.refetch); + watch( + [ + refetch, + toRef2(url) + ], + ([refetch2]) => refetch2 && execute(), + { deep: true } + ); + const shell = { + isFinished: readonly(isFinished), + isFetching: readonly(isFetching), + statusCode, + response, + error, + data, + canAbort, + aborted, + abort, + execute, + onFetchResponse: responseEvent.on, + onFetchError: errorEvent.on, + onFetchFinally: finallyEvent.on, + // method + get: setMethod("GET"), + put: setMethod("PUT"), + post: setMethod("POST"), + delete: setMethod("DELETE"), + patch: setMethod("PATCH"), + head: setMethod("HEAD"), + options: setMethod("OPTIONS"), + // type + json: setType("json"), + text: setType("text"), + blob: setType("blob"), + arrayBuffer: setType("arrayBuffer"), + formData: setType("formData") + }; + function setMethod(method) { + return (payload, payloadType) => { + if (!isFetching.value) { + config.method = method; + config.payload = payload; + config.payloadType = payloadType; + if (isRef(config.payload)) { + watch( + [ + refetch, + toRef2(config.payload) + ], + ([refetch2]) => refetch2 && execute(), + { deep: true } + ); + } + return { + ...shell, + then(onFulfilled, onRejected) { + return waitUntilFinished().then(onFulfilled, onRejected); + } + }; + } + return void 0; + }; + } + function waitUntilFinished() { + return new Promise((resolve, reject) => { + until(isFinished).toBe(true).then(() => resolve(shell)).catch(reject); + }); + } + function setType(type) { + return () => { + if (!isFetching.value) { + config.type = type; + return { + ...shell, + then(onFulfilled, onRejected) { + return waitUntilFinished().then(onFulfilled, onRejected); + } + }; + } + return void 0; + }; + } + if (options.immediate) + Promise.resolve().then(() => execute()); + return { + ...shell, + then(onFulfilled, onRejected) { + return waitUntilFinished().then(onFulfilled, onRejected); + } + }; +} +function joinPaths(start, end) { + if (!start.endsWith("/") && !end.startsWith("/")) { + return `${start}/${end}`; + } + if (start.endsWith("/") && end.startsWith("/")) { + return `${start.slice(0, -1)}${end}`; + } + return `${start}${end}`; +} +var DEFAULT_OPTIONS = { + multiple: true, + accept: "*", + reset: false, + directory: false +}; +function prepareInitialFiles(files) { + if (!files) + return null; + if (files instanceof FileList) + return files; + const dt = new DataTransfer(); + for (const file of files) { + dt.items.add(file); + } + return dt.files; +} +function useFileDialog(options = {}) { + const { + document: document2 = defaultDocument + } = options; + const files = ref(prepareInitialFiles(options.initialFiles)); + const { on: onChange, trigger: changeTrigger } = createEventHook(); + const { on: onCancel, trigger: cancelTrigger } = createEventHook(); + let input; + if (document2) { + input = document2.createElement("input"); + input.type = "file"; + input.onchange = (event) => { + const result = event.target; + files.value = result.files; + changeTrigger(files.value); + }; + input.oncancel = () => { + cancelTrigger(); + }; + } + const reset = () => { + files.value = null; + if (input && input.value) { + input.value = ""; + changeTrigger(null); + } + }; + const open = (localOptions) => { + if (!input) + return; + const _options = { + ...DEFAULT_OPTIONS, + ...options, + ...localOptions + }; + input.multiple = _options.multiple; + input.accept = _options.accept; + input.webkitdirectory = _options.directory; + if (hasOwn(_options, "capture")) + input.capture = _options.capture; + if (_options.reset) + reset(); + input.click(); + }; + return { + files: readonly(files), + open, + reset, + onCancel, + onChange + }; +} +function useFileSystemAccess(options = {}) { + const { + window: _window = defaultWindow, + dataType = "Text" + } = options; + const window2 = _window; + const isSupported = useSupported(() => window2 && "showSaveFilePicker" in window2 && "showOpenFilePicker" in window2); + const fileHandle = shallowRef(); + const data = shallowRef(); + const file = shallowRef(); + const fileName = computed(() => { + var _a, _b; + return (_b = (_a = file.value) == null ? void 0 : _a.name) != null ? _b : ""; + }); + const fileMIME = computed(() => { + var _a, _b; + return (_b = (_a = file.value) == null ? void 0 : _a.type) != null ? _b : ""; + }); + const fileSize = computed(() => { + var _a, _b; + return (_b = (_a = file.value) == null ? void 0 : _a.size) != null ? _b : 0; + }); + const fileLastModified = computed(() => { + var _a, _b; + return (_b = (_a = file.value) == null ? void 0 : _a.lastModified) != null ? _b : 0; + }); + async function open(_options = {}) { + if (!isSupported.value) + return; + const [handle] = await window2.showOpenFilePicker({ ...toValue(options), ..._options }); + fileHandle.value = handle; + await updateData(); + } + async function create(_options = {}) { + if (!isSupported.value) + return; + fileHandle.value = await window2.showSaveFilePicker({ ...options, ..._options }); + data.value = void 0; + await updateData(); + } + async function save(_options = {}) { + if (!isSupported.value) + return; + if (!fileHandle.value) + return saveAs(_options); + if (data.value) { + const writableStream = await fileHandle.value.createWritable(); + await writableStream.write(data.value); + await writableStream.close(); + } + await updateFile(); + } + async function saveAs(_options = {}) { + if (!isSupported.value) + return; + fileHandle.value = await window2.showSaveFilePicker({ ...options, ..._options }); + if (data.value) { + const writableStream = await fileHandle.value.createWritable(); + await writableStream.write(data.value); + await writableStream.close(); + } + await updateFile(); + } + async function updateFile() { + var _a; + file.value = await ((_a = fileHandle.value) == null ? void 0 : _a.getFile()); + } + async function updateData() { + var _a, _b; + await updateFile(); + const type = toValue(dataType); + if (type === "Text") + data.value = await ((_a = file.value) == null ? void 0 : _a.text()); + else if (type === "ArrayBuffer") + data.value = await ((_b = file.value) == null ? void 0 : _b.arrayBuffer()); + else if (type === "Blob") + data.value = file.value; + } + watch(() => toValue(dataType), updateData); + return { + isSupported, + data, + file, + fileName, + fileMIME, + fileSize, + fileLastModified, + open, + create, + save, + saveAs, + updateData + }; +} +function useFocus(target, options = {}) { + const { initialValue = false, focusVisible = false, preventScroll = false } = options; + const innerFocused = shallowRef(false); + const targetElement = computed(() => unrefElement(target)); + const listenerOptions = { passive: true }; + useEventListener(targetElement, "focus", (event) => { + var _a, _b; + if (!focusVisible || ((_b = (_a = event.target).matches) == null ? void 0 : _b.call(_a, ":focus-visible"))) + innerFocused.value = true; + }, listenerOptions); + useEventListener(targetElement, "blur", () => innerFocused.value = false, listenerOptions); + const focused = computed({ + get: () => innerFocused.value, + set(value) { + var _a, _b; + if (!value && innerFocused.value) + (_a = targetElement.value) == null ? void 0 : _a.blur(); + else if (value && !innerFocused.value) + (_b = targetElement.value) == null ? void 0 : _b.focus({ preventScroll }); + } + }); + watch( + targetElement, + () => { + focused.value = initialValue; + }, + { immediate: true, flush: "post" } + ); + return { focused }; +} +var EVENT_FOCUS_IN = "focusin"; +var EVENT_FOCUS_OUT = "focusout"; +var PSEUDO_CLASS_FOCUS_WITHIN = ":focus-within"; +function useFocusWithin(target, options = {}) { + const { window: window2 = defaultWindow } = options; + const targetElement = computed(() => unrefElement(target)); + const _focused = shallowRef(false); + const focused = computed(() => _focused.value); + const activeElement = useActiveElement(options); + if (!window2 || !activeElement.value) { + return { focused }; + } + const listenerOptions = { passive: true }; + useEventListener(targetElement, EVENT_FOCUS_IN, () => _focused.value = true, listenerOptions); + useEventListener(targetElement, EVENT_FOCUS_OUT, () => { + var _a, _b, _c; + return _focused.value = (_c = (_b = (_a = targetElement.value) == null ? void 0 : _a.matches) == null ? void 0 : _b.call(_a, PSEUDO_CLASS_FOCUS_WITHIN)) != null ? _c : false; + }, listenerOptions); + return { focused }; +} +function useFps(options) { + var _a; + const fps = shallowRef(0); + if (typeof performance === "undefined") + return fps; + const every = (_a = options == null ? void 0 : options.every) != null ? _a : 10; + let last = performance.now(); + let ticks = 0; + useRafFn(() => { + ticks += 1; + if (ticks >= every) { + const now2 = performance.now(); + const diff = now2 - last; + fps.value = Math.round(1e3 / (diff / ticks)); + last = now2; + ticks = 0; + } + }); + return fps; +} +var eventHandlers = [ + "fullscreenchange", + "webkitfullscreenchange", + "webkitendfullscreen", + "mozfullscreenchange", + "MSFullscreenChange" +]; +function useFullscreen(target, options = {}) { + const { + document: document2 = defaultDocument, + autoExit = false + } = options; + const targetRef = computed(() => { + var _a; + return (_a = unrefElement(target)) != null ? _a : document2 == null ? void 0 : document2.documentElement; + }); + const isFullscreen = shallowRef(false); + const requestMethod = computed(() => { + return [ + "requestFullscreen", + "webkitRequestFullscreen", + "webkitEnterFullscreen", + "webkitEnterFullScreen", + "webkitRequestFullScreen", + "mozRequestFullScreen", + "msRequestFullscreen" + ].find((m) => document2 && m in document2 || targetRef.value && m in targetRef.value); + }); + const exitMethod = computed(() => { + return [ + "exitFullscreen", + "webkitExitFullscreen", + "webkitExitFullScreen", + "webkitCancelFullScreen", + "mozCancelFullScreen", + "msExitFullscreen" + ].find((m) => document2 && m in document2 || targetRef.value && m in targetRef.value); + }); + const fullscreenEnabled = computed(() => { + return [ + "fullScreen", + "webkitIsFullScreen", + "webkitDisplayingFullscreen", + "mozFullScreen", + "msFullscreenElement" + ].find((m) => document2 && m in document2 || targetRef.value && m in targetRef.value); + }); + const fullscreenElementMethod = [ + "fullscreenElement", + "webkitFullscreenElement", + "mozFullScreenElement", + "msFullscreenElement" + ].find((m) => document2 && m in document2); + const isSupported = useSupported(() => targetRef.value && document2 && requestMethod.value !== void 0 && exitMethod.value !== void 0 && fullscreenEnabled.value !== void 0); + const isCurrentElementFullScreen = () => { + if (fullscreenElementMethod) + return (document2 == null ? void 0 : document2[fullscreenElementMethod]) === targetRef.value; + return false; + }; + const isElementFullScreen = () => { + if (fullscreenEnabled.value) { + if (document2 && document2[fullscreenEnabled.value] != null) { + return document2[fullscreenEnabled.value]; + } else { + const target2 = targetRef.value; + if ((target2 == null ? void 0 : target2[fullscreenEnabled.value]) != null) { + return Boolean(target2[fullscreenEnabled.value]); + } + } + } + return false; + }; + async function exit() { + if (!isSupported.value || !isFullscreen.value) + return; + if (exitMethod.value) { + if ((document2 == null ? void 0 : document2[exitMethod.value]) != null) { + await document2[exitMethod.value](); + } else { + const target2 = targetRef.value; + if ((target2 == null ? void 0 : target2[exitMethod.value]) != null) + await target2[exitMethod.value](); + } + } + isFullscreen.value = false; + } + async function enter() { + if (!isSupported.value || isFullscreen.value) + return; + if (isElementFullScreen()) + await exit(); + const target2 = targetRef.value; + if (requestMethod.value && (target2 == null ? void 0 : target2[requestMethod.value]) != null) { + await target2[requestMethod.value](); + isFullscreen.value = true; + } + } + async function toggle() { + await (isFullscreen.value ? exit() : enter()); + } + const handlerCallback = () => { + const isElementFullScreenValue = isElementFullScreen(); + if (!isElementFullScreenValue || isElementFullScreenValue && isCurrentElementFullScreen()) + isFullscreen.value = isElementFullScreenValue; + }; + const listenerOptions = { capture: false, passive: true }; + useEventListener(document2, eventHandlers, handlerCallback, listenerOptions); + useEventListener(() => unrefElement(targetRef), eventHandlers, handlerCallback, listenerOptions); + if (autoExit) + tryOnScopeDispose(exit); + return { + isSupported, + isFullscreen, + enter, + exit, + toggle + }; +} +function mapGamepadToXbox360Controller(gamepad) { + return computed(() => { + if (gamepad.value) { + return { + buttons: { + a: gamepad.value.buttons[0], + b: gamepad.value.buttons[1], + x: gamepad.value.buttons[2], + y: gamepad.value.buttons[3] + }, + bumper: { + left: gamepad.value.buttons[4], + right: gamepad.value.buttons[5] + }, + triggers: { + left: gamepad.value.buttons[6], + right: gamepad.value.buttons[7] + }, + stick: { + left: { + horizontal: gamepad.value.axes[0], + vertical: gamepad.value.axes[1], + button: gamepad.value.buttons[10] + }, + right: { + horizontal: gamepad.value.axes[2], + vertical: gamepad.value.axes[3], + button: gamepad.value.buttons[11] + } + }, + dpad: { + up: gamepad.value.buttons[12], + down: gamepad.value.buttons[13], + left: gamepad.value.buttons[14], + right: gamepad.value.buttons[15] + }, + back: gamepad.value.buttons[8], + start: gamepad.value.buttons[9] + }; + } + return null; + }); +} +function useGamepad(options = {}) { + const { + navigator: navigator2 = defaultNavigator + } = options; + const isSupported = useSupported(() => navigator2 && "getGamepads" in navigator2); + const gamepads = ref([]); + const onConnectedHook = createEventHook(); + const onDisconnectedHook = createEventHook(); + const stateFromGamepad = (gamepad) => { + const hapticActuators = []; + const vibrationActuator = "vibrationActuator" in gamepad ? gamepad.vibrationActuator : null; + if (vibrationActuator) + hapticActuators.push(vibrationActuator); + if (gamepad.hapticActuators) + hapticActuators.push(...gamepad.hapticActuators); + return { + id: gamepad.id, + index: gamepad.index, + connected: gamepad.connected, + mapping: gamepad.mapping, + timestamp: gamepad.timestamp, + vibrationActuator: gamepad.vibrationActuator, + hapticActuators, + axes: gamepad.axes.map((axes) => axes), + buttons: gamepad.buttons.map((button) => ({ pressed: button.pressed, touched: button.touched, value: button.value })) + }; + }; + const updateGamepadState = () => { + const _gamepads = (navigator2 == null ? void 0 : navigator2.getGamepads()) || []; + for (const gamepad of _gamepads) { + if (gamepad && gamepads.value[gamepad.index]) + gamepads.value[gamepad.index] = stateFromGamepad(gamepad); + } + }; + const { isActive, pause, resume } = useRafFn(updateGamepadState); + const onGamepadConnected = (gamepad) => { + if (!gamepads.value.some(({ index }) => index === gamepad.index)) { + gamepads.value.push(stateFromGamepad(gamepad)); + onConnectedHook.trigger(gamepad.index); + } + resume(); + }; + const onGamepadDisconnected = (gamepad) => { + gamepads.value = gamepads.value.filter((x) => x.index !== gamepad.index); + onDisconnectedHook.trigger(gamepad.index); + }; + const listenerOptions = { passive: true }; + useEventListener("gamepadconnected", (e) => onGamepadConnected(e.gamepad), listenerOptions); + useEventListener("gamepaddisconnected", (e) => onGamepadDisconnected(e.gamepad), listenerOptions); + tryOnMounted(() => { + const _gamepads = (navigator2 == null ? void 0 : navigator2.getGamepads()) || []; + for (const gamepad of _gamepads) { + if (gamepad && gamepads.value[gamepad.index]) + onGamepadConnected(gamepad); + } + }); + pause(); + return { + isSupported, + onConnected: onConnectedHook.on, + onDisconnected: onDisconnectedHook.on, + gamepads, + pause, + resume, + isActive + }; +} +function useGeolocation(options = {}) { + const { + enableHighAccuracy = true, + maximumAge = 3e4, + timeout = 27e3, + navigator: navigator2 = defaultNavigator, + immediate = true + } = options; + const isSupported = useSupported(() => navigator2 && "geolocation" in navigator2); + const locatedAt = shallowRef(null); + const error = shallowRef(null); + const coords = ref({ + accuracy: 0, + latitude: Number.POSITIVE_INFINITY, + longitude: Number.POSITIVE_INFINITY, + altitude: null, + altitudeAccuracy: null, + heading: null, + speed: null + }); + function updatePosition(position) { + locatedAt.value = position.timestamp; + coords.value = position.coords; + error.value = null; + } + let watcher; + function resume() { + if (isSupported.value) { + watcher = navigator2.geolocation.watchPosition( + updatePosition, + (err) => error.value = err, + { + enableHighAccuracy, + maximumAge, + timeout + } + ); + } + } + if (immediate) + resume(); + function pause() { + if (watcher && navigator2) + navigator2.geolocation.clearWatch(watcher); + } + tryOnScopeDispose(() => { + pause(); + }); + return { + isSupported, + coords, + locatedAt, + error, + resume, + pause + }; +} +var defaultEvents$1 = ["mousemove", "mousedown", "resize", "keydown", "touchstart", "wheel"]; +var oneMinute = 6e4; +function useIdle(timeout = oneMinute, options = {}) { + const { + initialState = false, + listenForVisibilityChange = true, + events: events2 = defaultEvents$1, + window: window2 = defaultWindow, + eventFilter = throttleFilter(50) + } = options; + const idle = shallowRef(initialState); + const lastActive = shallowRef(timestamp()); + let timer; + const reset = () => { + idle.value = false; + clearTimeout(timer); + timer = setTimeout(() => idle.value = true, timeout); + }; + const onEvent = createFilterWrapper( + eventFilter, + () => { + lastActive.value = timestamp(); + reset(); + } + ); + if (window2) { + const document2 = window2.document; + const listenerOptions = { passive: true }; + for (const event of events2) + useEventListener(window2, event, onEvent, listenerOptions); + if (listenForVisibilityChange) { + useEventListener(document2, "visibilitychange", () => { + if (!document2.hidden) + onEvent(); + }, listenerOptions); + } + reset(); + } + return { + idle, + lastActive, + reset + }; +} +async function loadImage(options) { + return new Promise((resolve, reject) => { + const img = new Image(); + const { src, srcset, sizes, class: clazz, loading, crossorigin, referrerPolicy, width, height, decoding, fetchPriority, ismap, usemap } = options; + img.src = src; + if (srcset != null) + img.srcset = srcset; + if (sizes != null) + img.sizes = sizes; + if (clazz != null) + img.className = clazz; + if (loading != null) + img.loading = loading; + if (crossorigin != null) + img.crossOrigin = crossorigin; + if (referrerPolicy != null) + img.referrerPolicy = referrerPolicy; + if (width != null) + img.width = width; + if (height != null) + img.height = height; + if (decoding != null) + img.decoding = decoding; + if (fetchPriority != null) + img.fetchPriority = fetchPriority; + if (ismap != null) + img.isMap = ismap; + if (usemap != null) + img.useMap = usemap; + img.onload = () => resolve(img); + img.onerror = reject; + }); +} +function useImage(options, asyncStateOptions = {}) { + const state = useAsyncState( + () => loadImage(toValue(options)), + void 0, + { + resetOnExecute: true, + ...asyncStateOptions + } + ); + watch( + () => toValue(options), + () => state.execute(asyncStateOptions.delay), + { deep: true } + ); + return state; +} +function resolveElement(el) { + if (typeof Window !== "undefined" && el instanceof Window) + return el.document.documentElement; + if (typeof Document !== "undefined" && el instanceof Document) + return el.documentElement; + return el; +} +var ARRIVED_STATE_THRESHOLD_PIXELS = 1; +function useScroll(element, options = {}) { + const { + throttle = 0, + idle = 200, + onStop = noop, + onScroll = noop, + offset = { + left: 0, + right: 0, + top: 0, + bottom: 0 + }, + eventListenerOptions = { + capture: false, + passive: true + }, + behavior = "auto", + window: window2 = defaultWindow, + onError = (e) => { + console.error(e); + } + } = options; + const internalX = shallowRef(0); + const internalY = shallowRef(0); + const x = computed({ + get() { + return internalX.value; + }, + set(x2) { + scrollTo(x2, void 0); + } + }); + const y = computed({ + get() { + return internalY.value; + }, + set(y2) { + scrollTo(void 0, y2); + } + }); + function scrollTo(_x, _y) { + var _a, _b, _c, _d; + if (!window2) + return; + const _element = toValue(element); + if (!_element) + return; + (_c = _element instanceof Document ? window2.document.body : _element) == null ? void 0 : _c.scrollTo({ + top: (_a = toValue(_y)) != null ? _a : y.value, + left: (_b = toValue(_x)) != null ? _b : x.value, + behavior: toValue(behavior) + }); + const scrollContainer = ((_d = _element == null ? void 0 : _element.document) == null ? void 0 : _d.documentElement) || (_element == null ? void 0 : _element.documentElement) || _element; + if (x != null) + internalX.value = scrollContainer.scrollLeft; + if (y != null) + internalY.value = scrollContainer.scrollTop; + } + const isScrolling = shallowRef(false); + const arrivedState = reactive({ + left: true, + right: false, + top: true, + bottom: false + }); + const directions = reactive({ + left: false, + right: false, + top: false, + bottom: false + }); + const onScrollEnd = (e) => { + if (!isScrolling.value) + return; + isScrolling.value = false; + directions.left = false; + directions.right = false; + directions.top = false; + directions.bottom = false; + onStop(e); + }; + const onScrollEndDebounced = useDebounceFn(onScrollEnd, throttle + idle); + const setArrivedState = (target) => { + var _a; + if (!window2) + return; + const el = ((_a = target == null ? void 0 : target.document) == null ? void 0 : _a.documentElement) || (target == null ? void 0 : target.documentElement) || unrefElement(target); + const { display, flexDirection, direction } = getComputedStyle(el); + const directionMultipler = direction === "rtl" ? -1 : 1; + const scrollLeft = el.scrollLeft; + directions.left = scrollLeft < internalX.value; + directions.right = scrollLeft > internalX.value; + const left = Math.abs(scrollLeft * directionMultipler) <= (offset.left || 0); + const right = Math.abs(scrollLeft * directionMultipler) + el.clientWidth >= el.scrollWidth - (offset.right || 0) - ARRIVED_STATE_THRESHOLD_PIXELS; + if (display === "flex" && flexDirection === "row-reverse") { + arrivedState.left = right; + arrivedState.right = left; + } else { + arrivedState.left = left; + arrivedState.right = right; + } + internalX.value = scrollLeft; + let scrollTop = el.scrollTop; + if (target === window2.document && !scrollTop) + scrollTop = window2.document.body.scrollTop; + directions.top = scrollTop < internalY.value; + directions.bottom = scrollTop > internalY.value; + const top = Math.abs(scrollTop) <= (offset.top || 0); + const bottom = Math.abs(scrollTop) + el.clientHeight >= el.scrollHeight - (offset.bottom || 0) - ARRIVED_STATE_THRESHOLD_PIXELS; + if (display === "flex" && flexDirection === "column-reverse") { + arrivedState.top = bottom; + arrivedState.bottom = top; + } else { + arrivedState.top = top; + arrivedState.bottom = bottom; + } + internalY.value = scrollTop; + }; + const onScrollHandler = (e) => { + var _a; + if (!window2) + return; + const eventTarget = (_a = e.target.documentElement) != null ? _a : e.target; + setArrivedState(eventTarget); + isScrolling.value = true; + onScrollEndDebounced(e); + onScroll(e); + }; + useEventListener( + element, + "scroll", + throttle ? useThrottleFn(onScrollHandler, throttle, true, false) : onScrollHandler, + eventListenerOptions + ); + tryOnMounted(() => { + try { + const _element = toValue(element); + if (!_element) + return; + setArrivedState(_element); + } catch (e) { + onError(e); + } + }); + useEventListener( + element, + "scrollend", + onScrollEnd, + eventListenerOptions + ); + return { + x, + y, + isScrolling, + arrivedState, + directions, + measure() { + const _element = toValue(element); + if (window2 && _element) + setArrivedState(_element); + } + }; +} +function useInfiniteScroll(element, onLoadMore, options = {}) { + var _a; + const { + direction = "bottom", + interval = 100, + canLoadMore = () => true + } = options; + const state = reactive(useScroll( + element, + { + ...options, + offset: { + [direction]: (_a = options.distance) != null ? _a : 0, + ...options.offset + } + } + )); + const promise = ref(); + const isLoading = computed(() => !!promise.value); + const observedElement = computed(() => { + return resolveElement(toValue(element)); + }); + const isElementVisible = useElementVisibility(observedElement); + function checkAndLoad() { + state.measure(); + if (!observedElement.value || !isElementVisible.value || !canLoadMore(observedElement.value)) + return; + const { scrollHeight, clientHeight, scrollWidth, clientWidth } = observedElement.value; + const isNarrower = direction === "bottom" || direction === "top" ? scrollHeight <= clientHeight : scrollWidth <= clientWidth; + if (state.arrivedState[direction] || isNarrower) { + if (!promise.value) { + promise.value = Promise.all([ + onLoadMore(state), + new Promise((resolve) => setTimeout(resolve, interval)) + ]).finally(() => { + promise.value = null; + nextTick(() => checkAndLoad()); + }); + } + } + } + const stop = watch( + () => [state.arrivedState[direction], isElementVisible.value], + checkAndLoad, + { immediate: true } + ); + tryOnUnmounted(stop); + return { + isLoading, + reset() { + nextTick(() => checkAndLoad()); + } + }; +} +var defaultEvents = ["mousedown", "mouseup", "keydown", "keyup"]; +function useKeyModifier(modifier, options = {}) { + const { + events: events2 = defaultEvents, + document: document2 = defaultDocument, + initial = null + } = options; + const state = shallowRef(initial); + if (document2) { + events2.forEach((listenerEvent) => { + useEventListener(document2, listenerEvent, (evt) => { + if (typeof evt.getModifierState === "function") + state.value = evt.getModifierState(modifier); + }, { passive: true }); + }); + } + return state; +} +function useLocalStorage(key, initialValue, options = {}) { + const { window: window2 = defaultWindow } = options; + return useStorage(key, initialValue, window2 == null ? void 0 : window2.localStorage, options); +} +var DefaultMagicKeysAliasMap = { + ctrl: "control", + command: "meta", + cmd: "meta", + option: "alt", + up: "arrowup", + down: "arrowdown", + left: "arrowleft", + right: "arrowright" +}; +function useMagicKeys(options = {}) { + const { + reactive: useReactive = false, + target = defaultWindow, + aliasMap = DefaultMagicKeysAliasMap, + passive = true, + onEventFired = noop + } = options; + const current = reactive(/* @__PURE__ */ new Set()); + const obj = { + toJSON() { + return {}; + }, + current + }; + const refs = useReactive ? reactive(obj) : obj; + const metaDeps = /* @__PURE__ */ new Set(); + const usedKeys = /* @__PURE__ */ new Set(); + function setRefs(key, value) { + if (key in refs) { + if (useReactive) + refs[key] = value; + else + refs[key].value = value; + } + } + function reset() { + current.clear(); + for (const key of usedKeys) + setRefs(key, false); + } + function updateRefs(e, value) { + var _a, _b; + const key = (_a = e.key) == null ? void 0 : _a.toLowerCase(); + const code = (_b = e.code) == null ? void 0 : _b.toLowerCase(); + const values = [code, key].filter(Boolean); + if (key) { + if (value) + current.add(key); + else + current.delete(key); + } + for (const key2 of values) { + usedKeys.add(key2); + setRefs(key2, value); + } + if (key === "meta" && !value) { + metaDeps.forEach((key2) => { + current.delete(key2); + setRefs(key2, false); + }); + metaDeps.clear(); + } else if (typeof e.getModifierState === "function" && e.getModifierState("Meta") && value) { + [...current, ...values].forEach((key2) => metaDeps.add(key2)); + } + } + useEventListener(target, "keydown", (e) => { + updateRefs(e, true); + return onEventFired(e); + }, { passive }); + useEventListener(target, "keyup", (e) => { + updateRefs(e, false); + return onEventFired(e); + }, { passive }); + useEventListener("blur", reset, { passive }); + useEventListener("focus", reset, { passive }); + const proxy = new Proxy( + refs, + { + get(target2, prop, rec) { + if (typeof prop !== "string") + return Reflect.get(target2, prop, rec); + prop = prop.toLowerCase(); + if (prop in aliasMap) + prop = aliasMap[prop]; + if (!(prop in refs)) { + if (/[+_-]/.test(prop)) { + const keys2 = prop.split(/[+_-]/g).map((i) => i.trim()); + refs[prop] = computed(() => keys2.map((key) => toValue(proxy[key])).every(Boolean)); + } else { + refs[prop] = shallowRef(false); + } + } + const r = Reflect.get(target2, prop, rec); + return useReactive ? toValue(r) : r; + } + } + ); + return proxy; +} +function usingElRef(source, cb) { + if (toValue(source)) + cb(toValue(source)); +} +function timeRangeToArray(timeRanges) { + let ranges = []; + for (let i = 0; i < timeRanges.length; ++i) + ranges = [...ranges, [timeRanges.start(i), timeRanges.end(i)]]; + return ranges; +} +function tracksToArray(tracks) { + return Array.from(tracks).map(({ label, kind, language, mode, activeCues, cues, inBandMetadataTrackDispatchType }, id) => ({ id, label, kind, language, mode, activeCues, cues, inBandMetadataTrackDispatchType })); +} +var defaultOptions = { + src: "", + tracks: [] +}; +function useMediaControls(target, options = {}) { + target = toRef2(target); + options = { + ...defaultOptions, + ...options + }; + const { + document: document2 = defaultDocument + } = options; + const listenerOptions = { passive: true }; + const currentTime = shallowRef(0); + const duration = shallowRef(0); + const seeking = shallowRef(false); + const volume = shallowRef(1); + const waiting = shallowRef(false); + const ended = shallowRef(false); + const playing = shallowRef(false); + const rate = shallowRef(1); + const stalled = shallowRef(false); + const buffered = ref([]); + const tracks = ref([]); + const selectedTrack = shallowRef(-1); + const isPictureInPicture = shallowRef(false); + const muted = shallowRef(false); + const supportsPictureInPicture = document2 && "pictureInPictureEnabled" in document2; + const sourceErrorEvent = createEventHook(); + const playbackErrorEvent = createEventHook(); + const disableTrack = (track) => { + usingElRef(target, (el) => { + if (track) { + const id = typeof track === "number" ? track : track.id; + el.textTracks[id].mode = "disabled"; + } else { + for (let i = 0; i < el.textTracks.length; ++i) + el.textTracks[i].mode = "disabled"; + } + selectedTrack.value = -1; + }); + }; + const enableTrack = (track, disableTracks = true) => { + usingElRef(target, (el) => { + const id = typeof track === "number" ? track : track.id; + if (disableTracks) + disableTrack(); + el.textTracks[id].mode = "showing"; + selectedTrack.value = id; + }); + }; + const togglePictureInPicture = () => { + return new Promise((resolve, reject) => { + usingElRef(target, async (el) => { + if (supportsPictureInPicture) { + if (!isPictureInPicture.value) { + el.requestPictureInPicture().then(resolve).catch(reject); + } else { + document2.exitPictureInPicture().then(resolve).catch(reject); + } + } + }); + }); + }; + watchEffect(() => { + if (!document2) + return; + const el = toValue(target); + if (!el) + return; + const src = toValue(options.src); + let sources = []; + if (!src) + return; + if (typeof src === "string") + sources = [{ src }]; + else if (Array.isArray(src)) + sources = src; + else if (isObject(src)) + sources = [src]; + el.querySelectorAll("source").forEach((e) => { + e.remove(); + }); + sources.forEach(({ src: src2, type, media }) => { + const source = document2.createElement("source"); + source.setAttribute("src", src2); + source.setAttribute("type", type || ""); + source.setAttribute("media", media || ""); + useEventListener(source, "error", sourceErrorEvent.trigger, listenerOptions); + el.appendChild(source); + }); + el.load(); + }); + watch([target, volume], () => { + const el = toValue(target); + if (!el) + return; + el.volume = volume.value; + }); + watch([target, muted], () => { + const el = toValue(target); + if (!el) + return; + el.muted = muted.value; + }); + watch([target, rate], () => { + const el = toValue(target); + if (!el) + return; + el.playbackRate = rate.value; + }); + watchEffect(() => { + if (!document2) + return; + const textTracks = toValue(options.tracks); + const el = toValue(target); + if (!textTracks || !textTracks.length || !el) + return; + el.querySelectorAll("track").forEach((e) => e.remove()); + textTracks.forEach(({ default: isDefault, kind, label, src, srcLang }, i) => { + const track = document2.createElement("track"); + track.default = isDefault || false; + track.kind = kind; + track.label = label; + track.src = src; + track.srclang = srcLang; + if (track.default) + selectedTrack.value = i; + el.appendChild(track); + }); + }); + const { ignoreUpdates: ignoreCurrentTimeUpdates } = watchIgnorable(currentTime, (time) => { + const el = toValue(target); + if (!el) + return; + el.currentTime = time; + }); + const { ignoreUpdates: ignorePlayingUpdates } = watchIgnorable(playing, (isPlaying) => { + const el = toValue(target); + if (!el) + return; + if (isPlaying) { + el.play().catch((e) => { + playbackErrorEvent.trigger(e); + throw e; + }); + } else { + el.pause(); + } + }); + useEventListener( + target, + "timeupdate", + () => ignoreCurrentTimeUpdates(() => currentTime.value = toValue(target).currentTime), + listenerOptions + ); + useEventListener( + target, + "durationchange", + () => duration.value = toValue(target).duration, + listenerOptions + ); + useEventListener( + target, + "progress", + () => buffered.value = timeRangeToArray(toValue(target).buffered), + listenerOptions + ); + useEventListener( + target, + "seeking", + () => seeking.value = true, + listenerOptions + ); + useEventListener( + target, + "seeked", + () => seeking.value = false, + listenerOptions + ); + useEventListener( + target, + ["waiting", "loadstart"], + () => { + waiting.value = true; + ignorePlayingUpdates(() => playing.value = false); + }, + listenerOptions + ); + useEventListener( + target, + "loadeddata", + () => waiting.value = false, + listenerOptions + ); + useEventListener( + target, + "playing", + () => { + waiting.value = false; + ended.value = false; + ignorePlayingUpdates(() => playing.value = true); + }, + listenerOptions + ); + useEventListener( + target, + "ratechange", + () => rate.value = toValue(target).playbackRate, + listenerOptions + ); + useEventListener( + target, + "stalled", + () => stalled.value = true, + listenerOptions + ); + useEventListener( + target, + "ended", + () => ended.value = true, + listenerOptions + ); + useEventListener( + target, + "pause", + () => ignorePlayingUpdates(() => playing.value = false), + listenerOptions + ); + useEventListener( + target, + "play", + () => ignorePlayingUpdates(() => playing.value = true), + listenerOptions + ); + useEventListener( + target, + "enterpictureinpicture", + () => isPictureInPicture.value = true, + listenerOptions + ); + useEventListener( + target, + "leavepictureinpicture", + () => isPictureInPicture.value = false, + listenerOptions + ); + useEventListener( + target, + "volumechange", + () => { + const el = toValue(target); + if (!el) + return; + volume.value = el.volume; + muted.value = el.muted; + }, + listenerOptions + ); + const listeners = []; + const stop = watch([target], () => { + const el = toValue(target); + if (!el) + return; + stop(); + listeners[0] = useEventListener(el.textTracks, "addtrack", () => tracks.value = tracksToArray(el.textTracks), listenerOptions); + listeners[1] = useEventListener(el.textTracks, "removetrack", () => tracks.value = tracksToArray(el.textTracks), listenerOptions); + listeners[2] = useEventListener(el.textTracks, "change", () => tracks.value = tracksToArray(el.textTracks), listenerOptions); + }); + tryOnScopeDispose(() => listeners.forEach((listener) => listener())); + return { + currentTime, + duration, + waiting, + seeking, + ended, + stalled, + buffered, + playing, + rate, + // Volume + volume, + muted, + // Tracks + tracks, + selectedTrack, + enableTrack, + disableTrack, + // Picture in Picture + supportsPictureInPicture, + togglePictureInPicture, + isPictureInPicture, + // Events + onSourceError: sourceErrorEvent.on, + onPlaybackError: playbackErrorEvent.on + }; +} +function useMemoize(resolver, options) { + const initCache = () => { + if (options == null ? void 0 : options.cache) + return shallowReactive(options.cache); + return shallowReactive(/* @__PURE__ */ new Map()); + }; + const cache = initCache(); + const generateKey = (...args) => (options == null ? void 0 : options.getKey) ? options.getKey(...args) : JSON.stringify(args); + const _loadData = (key, ...args) => { + cache.set(key, resolver(...args)); + return cache.get(key); + }; + const loadData = (...args) => _loadData(generateKey(...args), ...args); + const deleteData = (...args) => { + cache.delete(generateKey(...args)); + }; + const clearData = () => { + cache.clear(); + }; + const memoized = (...args) => { + const key = generateKey(...args); + if (cache.has(key)) + return cache.get(key); + return _loadData(key, ...args); + }; + memoized.load = loadData; + memoized.delete = deleteData; + memoized.clear = clearData; + memoized.generateKey = generateKey; + memoized.cache = cache; + return memoized; +} +function useMemory(options = {}) { + const memory = ref(); + const isSupported = useSupported(() => typeof performance !== "undefined" && "memory" in performance); + if (isSupported.value) { + const { interval = 1e3 } = options; + useIntervalFn(() => { + memory.value = performance.memory; + }, interval, { immediate: options.immediate, immediateCallback: options.immediateCallback }); + } + return { isSupported, memory }; +} +var UseMouseBuiltinExtractors = { + page: (event) => [event.pageX, event.pageY], + client: (event) => [event.clientX, event.clientY], + screen: (event) => [event.screenX, event.screenY], + movement: (event) => event instanceof MouseEvent ? [event.movementX, event.movementY] : null +}; +function useMouse(options = {}) { + const { + type = "page", + touch = true, + resetOnTouchEnds = false, + initialValue = { x: 0, y: 0 }, + window: window2 = defaultWindow, + target = window2, + scroll = true, + eventFilter + } = options; + let _prevMouseEvent = null; + let _prevScrollX = 0; + let _prevScrollY = 0; + const x = shallowRef(initialValue.x); + const y = shallowRef(initialValue.y); + const sourceType = shallowRef(null); + const extractor = typeof type === "function" ? type : UseMouseBuiltinExtractors[type]; + const mouseHandler = (event) => { + const result = extractor(event); + _prevMouseEvent = event; + if (result) { + [x.value, y.value] = result; + sourceType.value = "mouse"; + } + if (window2) { + _prevScrollX = window2.scrollX; + _prevScrollY = window2.scrollY; + } + }; + const touchHandler = (event) => { + if (event.touches.length > 0) { + const result = extractor(event.touches[0]); + if (result) { + [x.value, y.value] = result; + sourceType.value = "touch"; + } + } + }; + const scrollHandler = () => { + if (!_prevMouseEvent || !window2) + return; + const pos = extractor(_prevMouseEvent); + if (_prevMouseEvent instanceof MouseEvent && pos) { + x.value = pos[0] + window2.scrollX - _prevScrollX; + y.value = pos[1] + window2.scrollY - _prevScrollY; + } + }; + const reset = () => { + x.value = initialValue.x; + y.value = initialValue.y; + }; + const mouseHandlerWrapper = eventFilter ? (event) => eventFilter(() => mouseHandler(event), {}) : (event) => mouseHandler(event); + const touchHandlerWrapper = eventFilter ? (event) => eventFilter(() => touchHandler(event), {}) : (event) => touchHandler(event); + const scrollHandlerWrapper = eventFilter ? () => eventFilter(() => scrollHandler(), {}) : () => scrollHandler(); + if (target) { + const listenerOptions = { passive: true }; + useEventListener(target, ["mousemove", "dragover"], mouseHandlerWrapper, listenerOptions); + if (touch && type !== "movement") { + useEventListener(target, ["touchstart", "touchmove"], touchHandlerWrapper, listenerOptions); + if (resetOnTouchEnds) + useEventListener(target, "touchend", reset, listenerOptions); + } + if (scroll && type === "page") + useEventListener(window2, "scroll", scrollHandlerWrapper, listenerOptions); + } + return { + x, + y, + sourceType + }; +} +function useMouseInElement(target, options = {}) { + const { + handleOutside = true, + window: window2 = defaultWindow + } = options; + const type = options.type || "page"; + const { x, y, sourceType } = useMouse(options); + const targetRef = shallowRef(target != null ? target : window2 == null ? void 0 : window2.document.body); + const elementX = shallowRef(0); + const elementY = shallowRef(0); + const elementPositionX = shallowRef(0); + const elementPositionY = shallowRef(0); + const elementHeight = shallowRef(0); + const elementWidth = shallowRef(0); + const isOutside = shallowRef(true); + let stop = () => { + }; + if (window2) { + stop = watch( + [targetRef, x, y], + () => { + const el = unrefElement(targetRef); + if (!el || !(el instanceof Element)) + return; + const { + left, + top, + width, + height + } = el.getBoundingClientRect(); + elementPositionX.value = left + (type === "page" ? window2.pageXOffset : 0); + elementPositionY.value = top + (type === "page" ? window2.pageYOffset : 0); + elementHeight.value = height; + elementWidth.value = width; + const elX = x.value - elementPositionX.value; + const elY = y.value - elementPositionY.value; + isOutside.value = width === 0 || height === 0 || elX < 0 || elY < 0 || elX > width || elY > height; + if (handleOutside || !isOutside.value) { + elementX.value = elX; + elementY.value = elY; + } + }, + { immediate: true } + ); + useEventListener( + document, + "mouseleave", + () => isOutside.value = true, + { passive: true } + ); + } + return { + x, + y, + sourceType, + elementX, + elementY, + elementPositionX, + elementPositionY, + elementHeight, + elementWidth, + isOutside, + stop + }; +} +function useMousePressed(options = {}) { + const { + touch = true, + drag = true, + capture = false, + initialValue = false, + window: window2 = defaultWindow + } = options; + const pressed = shallowRef(initialValue); + const sourceType = shallowRef(null); + if (!window2) { + return { + pressed, + sourceType + }; + } + const onPressed = (srcType) => (event) => { + var _a; + pressed.value = true; + sourceType.value = srcType; + (_a = options.onPressed) == null ? void 0 : _a.call(options, event); + }; + const onReleased = (event) => { + var _a; + pressed.value = false; + sourceType.value = null; + (_a = options.onReleased) == null ? void 0 : _a.call(options, event); + }; + const target = computed(() => unrefElement(options.target) || window2); + const listenerOptions = { passive: true, capture }; + useEventListener(target, "mousedown", onPressed("mouse"), listenerOptions); + useEventListener(window2, "mouseleave", onReleased, listenerOptions); + useEventListener(window2, "mouseup", onReleased, listenerOptions); + if (drag) { + useEventListener(target, "dragstart", onPressed("mouse"), listenerOptions); + useEventListener(window2, "drop", onReleased, listenerOptions); + useEventListener(window2, "dragend", onReleased, listenerOptions); + } + if (touch) { + useEventListener(target, "touchstart", onPressed("touch"), listenerOptions); + useEventListener(window2, "touchend", onReleased, listenerOptions); + useEventListener(window2, "touchcancel", onReleased, listenerOptions); + } + return { + pressed, + sourceType + }; +} +function useNavigatorLanguage(options = {}) { + const { window: window2 = defaultWindow } = options; + const navigator2 = window2 == null ? void 0 : window2.navigator; + const isSupported = useSupported(() => navigator2 && "language" in navigator2); + const language = shallowRef(navigator2 == null ? void 0 : navigator2.language); + useEventListener(window2, "languagechange", () => { + if (navigator2) + language.value = navigator2.language; + }, { passive: true }); + return { + isSupported, + language + }; +} +function useNetwork(options = {}) { + const { window: window2 = defaultWindow } = options; + const navigator2 = window2 == null ? void 0 : window2.navigator; + const isSupported = useSupported(() => navigator2 && "connection" in navigator2); + const isOnline = shallowRef(true); + const saveData = shallowRef(false); + const offlineAt = shallowRef(void 0); + const onlineAt = shallowRef(void 0); + const downlink = shallowRef(void 0); + const downlinkMax = shallowRef(void 0); + const rtt = shallowRef(void 0); + const effectiveType = shallowRef(void 0); + const type = shallowRef("unknown"); + const connection = isSupported.value && navigator2.connection; + function updateNetworkInformation() { + if (!navigator2) + return; + isOnline.value = navigator2.onLine; + offlineAt.value = isOnline.value ? void 0 : Date.now(); + onlineAt.value = isOnline.value ? Date.now() : void 0; + if (connection) { + downlink.value = connection.downlink; + downlinkMax.value = connection.downlinkMax; + effectiveType.value = connection.effectiveType; + rtt.value = connection.rtt; + saveData.value = connection.saveData; + type.value = connection.type; + } + } + const listenerOptions = { passive: true }; + if (window2) { + useEventListener(window2, "offline", () => { + isOnline.value = false; + offlineAt.value = Date.now(); + }, listenerOptions); + useEventListener(window2, "online", () => { + isOnline.value = true; + onlineAt.value = Date.now(); + }, listenerOptions); + } + if (connection) + useEventListener(connection, "change", updateNetworkInformation, listenerOptions); + updateNetworkInformation(); + return { + isSupported, + isOnline: readonly(isOnline), + saveData: readonly(saveData), + offlineAt: readonly(offlineAt), + onlineAt: readonly(onlineAt), + downlink: readonly(downlink), + downlinkMax: readonly(downlinkMax), + effectiveType: readonly(effectiveType), + rtt: readonly(rtt), + type: readonly(type) + }; +} +function useNow(options = {}) { + const { + controls: exposeControls = false, + interval = "requestAnimationFrame" + } = options; + const now2 = ref(/* @__PURE__ */ new Date()); + const update = () => now2.value = /* @__PURE__ */ new Date(); + const controls = interval === "requestAnimationFrame" ? useRafFn(update, { immediate: true }) : useIntervalFn(update, interval, { immediate: true }); + if (exposeControls) { + return { + now: now2, + ...controls + }; + } else { + return now2; + } +} +function useObjectUrl(object) { + const url = shallowRef(); + const release = () => { + if (url.value) + URL.revokeObjectURL(url.value); + url.value = void 0; + }; + watch( + () => toValue(object), + (newObject) => { + release(); + if (newObject) + url.value = URL.createObjectURL(newObject); + }, + { immediate: true } + ); + tryOnScopeDispose(release); + return readonly(url); +} +function useClamp(value, min, max) { + if (typeof value === "function" || isReadonly(value)) + return computed(() => clamp(toValue(value), toValue(min), toValue(max))); + const _value = ref(value); + return computed({ + get() { + return _value.value = clamp(_value.value, toValue(min), toValue(max)); + }, + set(value2) { + _value.value = clamp(value2, toValue(min), toValue(max)); + } + }); +} +function useOffsetPagination(options) { + const { + total = Number.POSITIVE_INFINITY, + pageSize = 10, + page = 1, + onPageChange = noop, + onPageSizeChange = noop, + onPageCountChange = noop + } = options; + const currentPageSize = useClamp(pageSize, 1, Number.POSITIVE_INFINITY); + const pageCount = computed(() => Math.max( + 1, + Math.ceil(toValue(total) / toValue(currentPageSize)) + )); + const currentPage = useClamp(page, 1, pageCount); + const isFirstPage = computed(() => currentPage.value === 1); + const isLastPage = computed(() => currentPage.value === pageCount.value); + if (isRef(page)) { + syncRef(page, currentPage, { + direction: isReadonly(page) ? "ltr" : "both" + }); + } + if (isRef(pageSize)) { + syncRef(pageSize, currentPageSize, { + direction: isReadonly(pageSize) ? "ltr" : "both" + }); + } + function prev() { + currentPage.value--; + } + function next() { + currentPage.value++; + } + const returnValue = { + currentPage, + currentPageSize, + pageCount, + isFirstPage, + isLastPage, + prev, + next + }; + watch(currentPage, () => { + onPageChange(reactive(returnValue)); + }); + watch(currentPageSize, () => { + onPageSizeChange(reactive(returnValue)); + }); + watch(pageCount, () => { + onPageCountChange(reactive(returnValue)); + }); + return returnValue; +} +function useOnline(options = {}) { + const { isOnline } = useNetwork(options); + return isOnline; +} +function usePageLeave(options = {}) { + const { window: window2 = defaultWindow } = options; + const isLeft = shallowRef(false); + const handler = (event) => { + if (!window2) + return; + event = event || window2.event; + const from = event.relatedTarget || event.toElement; + isLeft.value = !from; + }; + if (window2) { + const listenerOptions = { passive: true }; + useEventListener(window2, "mouseout", handler, listenerOptions); + useEventListener(window2.document, "mouseleave", handler, listenerOptions); + useEventListener(window2.document, "mouseenter", handler, listenerOptions); + } + return isLeft; +} +function useScreenOrientation(options = {}) { + const { + window: window2 = defaultWindow + } = options; + const isSupported = useSupported(() => window2 && "screen" in window2 && "orientation" in window2.screen); + const screenOrientation = isSupported.value ? window2.screen.orientation : {}; + const orientation = ref(screenOrientation.type); + const angle = shallowRef(screenOrientation.angle || 0); + if (isSupported.value) { + useEventListener(window2, "orientationchange", () => { + orientation.value = screenOrientation.type; + angle.value = screenOrientation.angle; + }, { passive: true }); + } + const lockOrientation = (type) => { + if (isSupported.value && typeof screenOrientation.lock === "function") + return screenOrientation.lock(type); + return Promise.reject(new Error("Not supported")); + }; + const unlockOrientation = () => { + if (isSupported.value && typeof screenOrientation.unlock === "function") + screenOrientation.unlock(); + }; + return { + isSupported, + orientation, + angle, + lockOrientation, + unlockOrientation + }; +} +function useParallax(target, options = {}) { + const { + deviceOrientationTiltAdjust = (i) => i, + deviceOrientationRollAdjust = (i) => i, + mouseTiltAdjust = (i) => i, + mouseRollAdjust = (i) => i, + window: window2 = defaultWindow + } = options; + const orientation = reactive(useDeviceOrientation({ window: window2 })); + const screenOrientation = reactive(useScreenOrientation({ window: window2 })); + const { + elementX: x, + elementY: y, + elementWidth: width, + elementHeight: height + } = useMouseInElement(target, { handleOutside: false, window: window2 }); + const source = computed(() => { + if (orientation.isSupported && (orientation.alpha != null && orientation.alpha !== 0 || orientation.gamma != null && orientation.gamma !== 0)) { + return "deviceOrientation"; + } + return "mouse"; + }); + const roll = computed(() => { + if (source.value === "deviceOrientation") { + let value; + switch (screenOrientation.orientation) { + case "landscape-primary": + value = orientation.gamma / 90; + break; + case "landscape-secondary": + value = -orientation.gamma / 90; + break; + case "portrait-primary": + value = -orientation.beta / 90; + break; + case "portrait-secondary": + value = orientation.beta / 90; + break; + default: + value = -orientation.beta / 90; + } + return deviceOrientationRollAdjust(value); + } else { + const value = -(y.value - height.value / 2) / height.value; + return mouseRollAdjust(value); + } + }); + const tilt = computed(() => { + if (source.value === "deviceOrientation") { + let value; + switch (screenOrientation.orientation) { + case "landscape-primary": + value = orientation.beta / 90; + break; + case "landscape-secondary": + value = -orientation.beta / 90; + break; + case "portrait-primary": + value = orientation.gamma / 90; + break; + case "portrait-secondary": + value = -orientation.gamma / 90; + break; + default: + value = orientation.gamma / 90; + } + return deviceOrientationTiltAdjust(value); + } else { + const value = (x.value - width.value / 2) / width.value; + return mouseTiltAdjust(value); + } + }); + return { roll, tilt, source }; +} +function useParentElement(element = useCurrentElement()) { + const parentElement = shallowRef(); + const update = () => { + const el = unrefElement(element); + if (el) + parentElement.value = el.parentElement; + }; + tryOnMounted(update); + watch(() => toValue(element), update); + return parentElement; +} +function usePerformanceObserver(options, callback) { + const { + window: window2 = defaultWindow, + immediate = true, + ...performanceOptions + } = options; + const isSupported = useSupported(() => window2 && "PerformanceObserver" in window2); + let observer; + const stop = () => { + observer == null ? void 0 : observer.disconnect(); + }; + const start = () => { + if (isSupported.value) { + stop(); + observer = new PerformanceObserver(callback); + observer.observe(performanceOptions); + } + }; + tryOnScopeDispose(stop); + if (immediate) + start(); + return { + isSupported, + start, + stop + }; +} +var defaultState = { + x: 0, + y: 0, + pointerId: 0, + pressure: 0, + tiltX: 0, + tiltY: 0, + width: 0, + height: 0, + twist: 0, + pointerType: null +}; +var keys = Object.keys(defaultState); +function usePointer(options = {}) { + const { + target = defaultWindow + } = options; + const isInside = shallowRef(false); + const state = ref(options.initialValue || {}); + Object.assign(state.value, defaultState, state.value); + const handler = (event) => { + isInside.value = true; + if (options.pointerTypes && !options.pointerTypes.includes(event.pointerType)) + return; + state.value = objectPick(event, keys, false); + }; + if (target) { + const listenerOptions = { passive: true }; + useEventListener(target, ["pointerdown", "pointermove", "pointerup"], handler, listenerOptions); + useEventListener(target, "pointerleave", () => isInside.value = false, listenerOptions); + } + return { + ...toRefs2(state), + isInside + }; +} +function usePointerLock(target, options = {}) { + const { document: document2 = defaultDocument } = options; + const isSupported = useSupported(() => document2 && "pointerLockElement" in document2); + const element = shallowRef(); + const triggerElement = shallowRef(); + let targetElement; + if (isSupported.value) { + const listenerOptions = { passive: true }; + useEventListener(document2, "pointerlockchange", () => { + var _a; + const currentElement = (_a = document2.pointerLockElement) != null ? _a : element.value; + if (targetElement && currentElement === targetElement) { + element.value = document2.pointerLockElement; + if (!element.value) + targetElement = triggerElement.value = null; + } + }, listenerOptions); + useEventListener(document2, "pointerlockerror", () => { + var _a; + const currentElement = (_a = document2.pointerLockElement) != null ? _a : element.value; + if (targetElement && currentElement === targetElement) { + const action = document2.pointerLockElement ? "release" : "acquire"; + throw new Error(`Failed to ${action} pointer lock.`); + } + }, listenerOptions); + } + async function lock(e) { + var _a; + if (!isSupported.value) + throw new Error("Pointer Lock API is not supported by your browser."); + triggerElement.value = e instanceof Event ? e.currentTarget : null; + targetElement = e instanceof Event ? (_a = unrefElement(target)) != null ? _a : triggerElement.value : unrefElement(e); + if (!targetElement) + throw new Error("Target element undefined."); + targetElement.requestPointerLock(); + return await until(element).toBe(targetElement); + } + async function unlock() { + if (!element.value) + return false; + document2.exitPointerLock(); + await until(element).toBeNull(); + return true; + } + return { + isSupported, + element, + triggerElement, + lock, + unlock + }; +} +function usePointerSwipe(target, options = {}) { + const targetRef = toRef2(target); + const { + threshold = 50, + onSwipe, + onSwipeEnd, + onSwipeStart, + disableTextSelect = false + } = options; + const posStart = reactive({ x: 0, y: 0 }); + const updatePosStart = (x, y) => { + posStart.x = x; + posStart.y = y; + }; + const posEnd = reactive({ x: 0, y: 0 }); + const updatePosEnd = (x, y) => { + posEnd.x = x; + posEnd.y = y; + }; + const distanceX = computed(() => posStart.x - posEnd.x); + const distanceY = computed(() => posStart.y - posEnd.y); + const { max, abs } = Math; + const isThresholdExceeded = computed(() => max(abs(distanceX.value), abs(distanceY.value)) >= threshold); + const isSwiping = shallowRef(false); + const isPointerDown = shallowRef(false); + const direction = computed(() => { + if (!isThresholdExceeded.value) + return "none"; + if (abs(distanceX.value) > abs(distanceY.value)) { + return distanceX.value > 0 ? "left" : "right"; + } else { + return distanceY.value > 0 ? "up" : "down"; + } + }); + const eventIsAllowed = (e) => { + var _a, _b, _c; + const isReleasingButton = e.buttons === 0; + const isPrimaryButton = e.buttons === 1; + return (_c = (_b = (_a = options.pointerTypes) == null ? void 0 : _a.includes(e.pointerType)) != null ? _b : isReleasingButton || isPrimaryButton) != null ? _c : true; + }; + const listenerOptions = { passive: true }; + const stops = [ + useEventListener(target, "pointerdown", (e) => { + if (!eventIsAllowed(e)) + return; + isPointerDown.value = true; + const eventTarget = e.target; + eventTarget == null ? void 0 : eventTarget.setPointerCapture(e.pointerId); + const { clientX: x, clientY: y } = e; + updatePosStart(x, y); + updatePosEnd(x, y); + onSwipeStart == null ? void 0 : onSwipeStart(e); + }, listenerOptions), + useEventListener(target, "pointermove", (e) => { + if (!eventIsAllowed(e)) + return; + if (!isPointerDown.value) + return; + const { clientX: x, clientY: y } = e; + updatePosEnd(x, y); + if (!isSwiping.value && isThresholdExceeded.value) + isSwiping.value = true; + if (isSwiping.value) + onSwipe == null ? void 0 : onSwipe(e); + }, listenerOptions), + useEventListener(target, "pointerup", (e) => { + if (!eventIsAllowed(e)) + return; + if (isSwiping.value) + onSwipeEnd == null ? void 0 : onSwipeEnd(e, direction.value); + isPointerDown.value = false; + isSwiping.value = false; + }, listenerOptions) + ]; + tryOnMounted(() => { + var _a, _b, _c, _d, _e, _f, _g, _h; + (_b = (_a = targetRef.value) == null ? void 0 : _a.style) == null ? void 0 : _b.setProperty("touch-action", "none"); + if (disableTextSelect) { + (_d = (_c = targetRef.value) == null ? void 0 : _c.style) == null ? void 0 : _d.setProperty("-webkit-user-select", "none"); + (_f = (_e = targetRef.value) == null ? void 0 : _e.style) == null ? void 0 : _f.setProperty("-ms-user-select", "none"); + (_h = (_g = targetRef.value) == null ? void 0 : _g.style) == null ? void 0 : _h.setProperty("user-select", "none"); + } + }); + const stop = () => stops.forEach((s) => s()); + return { + isSwiping: readonly(isSwiping), + direction: readonly(direction), + posStart: readonly(posStart), + posEnd: readonly(posEnd), + distanceX, + distanceY, + stop + }; +} +function usePreferredColorScheme(options) { + const isLight = useMediaQuery("(prefers-color-scheme: light)", options); + const isDark = useMediaQuery("(prefers-color-scheme: dark)", options); + return computed(() => { + if (isDark.value) + return "dark"; + if (isLight.value) + return "light"; + return "no-preference"; + }); +} +function usePreferredContrast(options) { + const isMore = useMediaQuery("(prefers-contrast: more)", options); + const isLess = useMediaQuery("(prefers-contrast: less)", options); + const isCustom = useMediaQuery("(prefers-contrast: custom)", options); + return computed(() => { + if (isMore.value) + return "more"; + if (isLess.value) + return "less"; + if (isCustom.value) + return "custom"; + return "no-preference"; + }); +} +function usePreferredLanguages(options = {}) { + const { window: window2 = defaultWindow } = options; + if (!window2) + return ref(["en"]); + const navigator2 = window2.navigator; + const value = ref(navigator2.languages); + useEventListener(window2, "languagechange", () => { + value.value = navigator2.languages; + }, { passive: true }); + return value; +} +function usePreferredReducedMotion(options) { + const isReduced = useMediaQuery("(prefers-reduced-motion: reduce)", options); + return computed(() => { + if (isReduced.value) + return "reduce"; + return "no-preference"; + }); +} +function usePreferredReducedTransparency(options) { + const isReduced = useMediaQuery("(prefers-reduced-transparency: reduce)", options); + return computed(() => { + if (isReduced.value) + return "reduce"; + return "no-preference"; + }); +} +function usePrevious(value, initialValue) { + const previous = shallowRef(initialValue); + watch( + toRef2(value), + (_, oldValue) => { + previous.value = oldValue; + }, + { flush: "sync" } + ); + return readonly(previous); +} +var topVarName = "--vueuse-safe-area-top"; +var rightVarName = "--vueuse-safe-area-right"; +var bottomVarName = "--vueuse-safe-area-bottom"; +var leftVarName = "--vueuse-safe-area-left"; +function useScreenSafeArea() { + const top = shallowRef(""); + const right = shallowRef(""); + const bottom = shallowRef(""); + const left = shallowRef(""); + if (isClient) { + const topCssVar = useCssVar(topVarName); + const rightCssVar = useCssVar(rightVarName); + const bottomCssVar = useCssVar(bottomVarName); + const leftCssVar = useCssVar(leftVarName); + topCssVar.value = "env(safe-area-inset-top, 0px)"; + rightCssVar.value = "env(safe-area-inset-right, 0px)"; + bottomCssVar.value = "env(safe-area-inset-bottom, 0px)"; + leftCssVar.value = "env(safe-area-inset-left, 0px)"; + update(); + useEventListener("resize", useDebounceFn(update), { passive: true }); + } + function update() { + top.value = getValue(topVarName); + right.value = getValue(rightVarName); + bottom.value = getValue(bottomVarName); + left.value = getValue(leftVarName); + } + return { + top, + right, + bottom, + left, + update + }; +} +function getValue(position) { + return getComputedStyle(document.documentElement).getPropertyValue(position); +} +function useScriptTag(src, onLoaded = noop, options = {}) { + const { + immediate = true, + manual = false, + type = "text/javascript", + async = true, + crossOrigin, + referrerPolicy, + noModule, + defer, + document: document2 = defaultDocument, + attrs = {} + } = options; + const scriptTag = shallowRef(null); + let _promise = null; + const loadScript = (waitForScriptLoad) => new Promise((resolve, reject) => { + const resolveWithElement = (el2) => { + scriptTag.value = el2; + resolve(el2); + return el2; + }; + if (!document2) { + resolve(false); + return; + } + let shouldAppend = false; + let el = document2.querySelector(`script[src="${toValue(src)}"]`); + if (!el) { + el = document2.createElement("script"); + el.type = type; + el.async = async; + el.src = toValue(src); + if (defer) + el.defer = defer; + if (crossOrigin) + el.crossOrigin = crossOrigin; + if (noModule) + el.noModule = noModule; + if (referrerPolicy) + el.referrerPolicy = referrerPolicy; + Object.entries(attrs).forEach(([name, value]) => el == null ? void 0 : el.setAttribute(name, value)); + shouldAppend = true; + } else if (el.hasAttribute("data-loaded")) { + resolveWithElement(el); + } + const listenerOptions = { + passive: true + }; + useEventListener(el, "error", (event) => reject(event), listenerOptions); + useEventListener(el, "abort", (event) => reject(event), listenerOptions); + useEventListener(el, "load", () => { + el.setAttribute("data-loaded", "true"); + onLoaded(el); + resolveWithElement(el); + }, listenerOptions); + if (shouldAppend) + el = document2.head.appendChild(el); + if (!waitForScriptLoad) + resolveWithElement(el); + }); + const load = (waitForScriptLoad = true) => { + if (!_promise) + _promise = loadScript(waitForScriptLoad); + return _promise; + }; + const unload = () => { + if (!document2) + return; + _promise = null; + if (scriptTag.value) + scriptTag.value = null; + const el = document2.querySelector(`script[src="${toValue(src)}"]`); + if (el) + document2.head.removeChild(el); + }; + if (immediate && !manual) + tryOnMounted(load); + if (!manual) + tryOnUnmounted(unload); + return { scriptTag, load, unload }; +} +function checkOverflowScroll(ele) { + const style = window.getComputedStyle(ele); + if (style.overflowX === "scroll" || style.overflowY === "scroll" || style.overflowX === "auto" && ele.clientWidth < ele.scrollWidth || style.overflowY === "auto" && ele.clientHeight < ele.scrollHeight) { + return true; + } else { + const parent = ele.parentNode; + if (!parent || parent.tagName === "BODY") + return false; + return checkOverflowScroll(parent); + } +} +function preventDefault(rawEvent) { + const e = rawEvent || window.event; + const _target = e.target; + if (checkOverflowScroll(_target)) + return false; + if (e.touches.length > 1) + return true; + if (e.preventDefault) + e.preventDefault(); + return false; +} +var elInitialOverflow = /* @__PURE__ */ new WeakMap(); +function useScrollLock(element, initialState = false) { + const isLocked = shallowRef(initialState); + let stopTouchMoveListener = null; + let initialOverflow = ""; + watch(toRef2(element), (el) => { + const target = resolveElement(toValue(el)); + if (target) { + const ele = target; + if (!elInitialOverflow.get(ele)) + elInitialOverflow.set(ele, ele.style.overflow); + if (ele.style.overflow !== "hidden") + initialOverflow = ele.style.overflow; + if (ele.style.overflow === "hidden") + return isLocked.value = true; + if (isLocked.value) + return ele.style.overflow = "hidden"; + } + }, { + immediate: true + }); + const lock = () => { + const el = resolveElement(toValue(element)); + if (!el || isLocked.value) + return; + if (isIOS) { + stopTouchMoveListener = useEventListener( + el, + "touchmove", + (e) => { + preventDefault(e); + }, + { passive: false } + ); + } + el.style.overflow = "hidden"; + isLocked.value = true; + }; + const unlock = () => { + const el = resolveElement(toValue(element)); + if (!el || !isLocked.value) + return; + if (isIOS) + stopTouchMoveListener == null ? void 0 : stopTouchMoveListener(); + el.style.overflow = initialOverflow; + elInitialOverflow.delete(el); + isLocked.value = false; + }; + tryOnScopeDispose(unlock); + return computed({ + get() { + return isLocked.value; + }, + set(v) { + if (v) + lock(); + else unlock(); + } + }); +} +function useSessionStorage(key, initialValue, options = {}) { + const { window: window2 = defaultWindow } = options; + return useStorage(key, initialValue, window2 == null ? void 0 : window2.sessionStorage, options); +} +function useShare(shareOptions = {}, options = {}) { + const { navigator: navigator2 = defaultNavigator } = options; + const _navigator = navigator2; + const isSupported = useSupported(() => _navigator && "canShare" in _navigator); + const share = async (overrideOptions = {}) => { + if (isSupported.value) { + const data = { + ...toValue(shareOptions), + ...toValue(overrideOptions) + }; + let granted = true; + if (data.files && _navigator.canShare) + granted = _navigator.canShare({ files: data.files }); + if (granted) + return _navigator.share(data); + } + }; + return { + isSupported, + share + }; +} +var defaultSortFn = (source, compareFn) => source.sort(compareFn); +var defaultCompare = (a, b) => a - b; +function useSorted(...args) { + var _a, _b, _c, _d; + const [source] = args; + let compareFn = defaultCompare; + let options = {}; + if (args.length === 2) { + if (typeof args[1] === "object") { + options = args[1]; + compareFn = (_a = options.compareFn) != null ? _a : defaultCompare; + } else { + compareFn = (_b = args[1]) != null ? _b : defaultCompare; + } + } else if (args.length > 2) { + compareFn = (_c = args[1]) != null ? _c : defaultCompare; + options = (_d = args[2]) != null ? _d : {}; + } + const { + dirty = false, + sortFn = defaultSortFn + } = options; + if (!dirty) + return computed(() => sortFn([...toValue(source)], compareFn)); + watchEffect(() => { + const result = sortFn(toValue(source), compareFn); + if (isRef(source)) + source.value = result; + else + source.splice(0, source.length, ...result); + }); + return source; +} +function useSpeechRecognition(options = {}) { + const { + interimResults = true, + continuous = true, + maxAlternatives = 1, + window: window2 = defaultWindow + } = options; + const lang = toRef2(options.lang || "en-US"); + const isListening = shallowRef(false); + const isFinal = shallowRef(false); + const result = shallowRef(""); + const error = shallowRef(void 0); + let recognition; + const start = () => { + isListening.value = true; + }; + const stop = () => { + isListening.value = false; + }; + const toggle = (value = !isListening.value) => { + if (value) { + start(); + } else { + stop(); + } + }; + const SpeechRecognition = window2 && (window2.SpeechRecognition || window2.webkitSpeechRecognition); + const isSupported = useSupported(() => SpeechRecognition); + if (isSupported.value) { + recognition = new SpeechRecognition(); + recognition.continuous = continuous; + recognition.interimResults = interimResults; + recognition.lang = toValue(lang); + recognition.maxAlternatives = maxAlternatives; + recognition.onstart = () => { + isListening.value = true; + isFinal.value = false; + }; + watch(lang, (lang2) => { + if (recognition && !isListening.value) + recognition.lang = lang2; + }); + recognition.onresult = (event) => { + const currentResult = event.results[event.resultIndex]; + const { transcript } = currentResult[0]; + isFinal.value = currentResult.isFinal; + result.value = transcript; + error.value = void 0; + }; + recognition.onerror = (event) => { + error.value = event; + }; + recognition.onend = () => { + isListening.value = false; + recognition.lang = toValue(lang); + }; + watch(isListening, (newValue, oldValue) => { + if (newValue === oldValue) + return; + if (newValue) + recognition.start(); + else + recognition.stop(); + }); + } + tryOnScopeDispose(() => { + stop(); + }); + return { + isSupported, + isListening, + isFinal, + recognition, + result, + error, + toggle, + start, + stop + }; +} +function useSpeechSynthesis(text, options = {}) { + const { + pitch = 1, + rate = 1, + volume = 1, + window: window2 = defaultWindow + } = options; + const synth = window2 && window2.speechSynthesis; + const isSupported = useSupported(() => synth); + const isPlaying = shallowRef(false); + const status = shallowRef("init"); + const spokenText = toRef2(text || ""); + const lang = toRef2(options.lang || "en-US"); + const error = shallowRef(void 0); + const toggle = (value = !isPlaying.value) => { + isPlaying.value = value; + }; + const bindEventsForUtterance = (utterance2) => { + utterance2.lang = toValue(lang); + utterance2.voice = toValue(options.voice) || null; + utterance2.pitch = toValue(pitch); + utterance2.rate = toValue(rate); + utterance2.volume = volume; + utterance2.onstart = () => { + isPlaying.value = true; + status.value = "play"; + }; + utterance2.onpause = () => { + isPlaying.value = false; + status.value = "pause"; + }; + utterance2.onresume = () => { + isPlaying.value = true; + status.value = "play"; + }; + utterance2.onend = () => { + isPlaying.value = false; + status.value = "end"; + }; + utterance2.onerror = (event) => { + error.value = event; + }; + }; + const utterance = computed(() => { + isPlaying.value = false; + status.value = "init"; + const newUtterance = new SpeechSynthesisUtterance(spokenText.value); + bindEventsForUtterance(newUtterance); + return newUtterance; + }); + const speak = () => { + synth.cancel(); + if (utterance) + synth.speak(utterance.value); + }; + const stop = () => { + synth.cancel(); + isPlaying.value = false; + }; + if (isSupported.value) { + bindEventsForUtterance(utterance.value); + watch(lang, (lang2) => { + if (utterance.value && !isPlaying.value) + utterance.value.lang = lang2; + }); + if (options.voice) { + watch(options.voice, () => { + synth.cancel(); + }); + } + watch(isPlaying, () => { + if (isPlaying.value) + synth.resume(); + else + synth.pause(); + }); + } + tryOnScopeDispose(() => { + isPlaying.value = false; + }); + return { + isSupported, + isPlaying, + status, + utterance, + error, + stop, + toggle, + speak + }; +} +function useStepper(steps, initialStep) { + const stepsRef = ref(steps); + const stepNames = computed(() => Array.isArray(stepsRef.value) ? stepsRef.value : Object.keys(stepsRef.value)); + const index = ref(stepNames.value.indexOf(initialStep != null ? initialStep : stepNames.value[0])); + const current = computed(() => at(index.value)); + const isFirst = computed(() => index.value === 0); + const isLast = computed(() => index.value === stepNames.value.length - 1); + const next = computed(() => stepNames.value[index.value + 1]); + const previous = computed(() => stepNames.value[index.value - 1]); + function at(index2) { + if (Array.isArray(stepsRef.value)) + return stepsRef.value[index2]; + return stepsRef.value[stepNames.value[index2]]; + } + function get2(step) { + if (!stepNames.value.includes(step)) + return; + return at(stepNames.value.indexOf(step)); + } + function goTo(step) { + if (stepNames.value.includes(step)) + index.value = stepNames.value.indexOf(step); + } + function goToNext() { + if (isLast.value) + return; + index.value++; + } + function goToPrevious() { + if (isFirst.value) + return; + index.value--; + } + function goBackTo(step) { + if (isAfter(step)) + goTo(step); + } + function isNext(step) { + return stepNames.value.indexOf(step) === index.value + 1; + } + function isPrevious(step) { + return stepNames.value.indexOf(step) === index.value - 1; + } + function isCurrent(step) { + return stepNames.value.indexOf(step) === index.value; + } + function isBefore(step) { + return index.value < stepNames.value.indexOf(step); + } + function isAfter(step) { + return index.value > stepNames.value.indexOf(step); + } + return { + steps: stepsRef, + stepNames, + index, + current, + next, + previous, + isFirst, + isLast, + at, + get: get2, + goTo, + goToNext, + goToPrevious, + goBackTo, + isNext, + isPrevious, + isCurrent, + isBefore, + isAfter + }; +} +function useStorageAsync(key, initialValue, storage, options = {}) { + var _a; + const { + flush = "pre", + deep = true, + listenToStorageChanges = true, + writeDefaults = true, + mergeDefaults = false, + shallow, + window: window2 = defaultWindow, + eventFilter, + onError = (e) => { + console.error(e); + } + } = options; + const rawInit = toValue(initialValue); + const type = guessSerializerType(rawInit); + const data = (shallow ? shallowRef : ref)(toValue(initialValue)); + const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type]; + if (!storage) { + try { + storage = getSSRHandler("getDefaultStorageAsync", () => { + var _a2; + return (_a2 = defaultWindow) == null ? void 0 : _a2.localStorage; + })(); + } catch (e) { + onError(e); + } + } + async function read(event) { + if (!storage || event && event.key !== key) + return; + try { + const rawValue = event ? event.newValue : await storage.getItem(key); + if (rawValue == null) { + data.value = rawInit; + if (writeDefaults && rawInit !== null) + await storage.setItem(key, await serializer.write(rawInit)); + } else if (mergeDefaults) { + const value = await serializer.read(rawValue); + if (typeof mergeDefaults === "function") + data.value = mergeDefaults(value, rawInit); + else if (type === "object" && !Array.isArray(value)) + data.value = { ...rawInit, ...value }; + else data.value = value; + } else { + data.value = await serializer.read(rawValue); + } + } catch (e) { + onError(e); + } + } + read(); + if (window2 && listenToStorageChanges) + useEventListener(window2, "storage", (e) => Promise.resolve().then(() => read(e)), { passive: true }); + if (storage) { + watchWithFilter( + data, + async () => { + try { + if (data.value == null) + await storage.removeItem(key); + else + await storage.setItem(key, await serializer.write(data.value)); + } catch (e) { + onError(e); + } + }, + { + flush, + deep, + eventFilter + } + ); + } + return data; +} +var _id = 0; +function useStyleTag(css, options = {}) { + const isLoaded = shallowRef(false); + const { + document: document2 = defaultDocument, + immediate = true, + manual = false, + id = `vueuse_styletag_${++_id}` + } = options; + const cssRef = shallowRef(css); + let stop = () => { + }; + const load = () => { + if (!document2) + return; + const el = document2.getElementById(id) || document2.createElement("style"); + if (!el.isConnected) { + el.id = id; + if (options.media) + el.media = options.media; + document2.head.appendChild(el); + } + if (isLoaded.value) + return; + stop = watch( + cssRef, + (value) => { + el.textContent = value; + }, + { immediate: true } + ); + isLoaded.value = true; + }; + const unload = () => { + if (!document2 || !isLoaded.value) + return; + stop(); + document2.head.removeChild(document2.getElementById(id)); + isLoaded.value = false; + }; + if (immediate && !manual) + tryOnMounted(load); + if (!manual) + tryOnScopeDispose(unload); + return { + id, + css: cssRef, + unload, + load, + isLoaded: readonly(isLoaded) + }; +} +function useSwipe(target, options = {}) { + const { + threshold = 50, + onSwipe, + onSwipeEnd, + onSwipeStart, + passive = true + } = options; + const coordsStart = reactive({ x: 0, y: 0 }); + const coordsEnd = reactive({ x: 0, y: 0 }); + const diffX = computed(() => coordsStart.x - coordsEnd.x); + const diffY = computed(() => coordsStart.y - coordsEnd.y); + const { max, abs } = Math; + const isThresholdExceeded = computed(() => max(abs(diffX.value), abs(diffY.value)) >= threshold); + const isSwiping = shallowRef(false); + const direction = computed(() => { + if (!isThresholdExceeded.value) + return "none"; + if (abs(diffX.value) > abs(diffY.value)) { + return diffX.value > 0 ? "left" : "right"; + } else { + return diffY.value > 0 ? "up" : "down"; + } + }); + const getTouchEventCoords = (e) => [e.touches[0].clientX, e.touches[0].clientY]; + const updateCoordsStart = (x, y) => { + coordsStart.x = x; + coordsStart.y = y; + }; + const updateCoordsEnd = (x, y) => { + coordsEnd.x = x; + coordsEnd.y = y; + }; + const listenerOptions = { passive, capture: !passive }; + const onTouchEnd = (e) => { + if (isSwiping.value) + onSwipeEnd == null ? void 0 : onSwipeEnd(e, direction.value); + isSwiping.value = false; + }; + const stops = [ + useEventListener(target, "touchstart", (e) => { + if (e.touches.length !== 1) + return; + const [x, y] = getTouchEventCoords(e); + updateCoordsStart(x, y); + updateCoordsEnd(x, y); + onSwipeStart == null ? void 0 : onSwipeStart(e); + }, listenerOptions), + useEventListener(target, "touchmove", (e) => { + if (e.touches.length !== 1) + return; + const [x, y] = getTouchEventCoords(e); + updateCoordsEnd(x, y); + if (listenerOptions.capture && !listenerOptions.passive && Math.abs(diffX.value) > Math.abs(diffY.value)) + e.preventDefault(); + if (!isSwiping.value && isThresholdExceeded.value) + isSwiping.value = true; + if (isSwiping.value) + onSwipe == null ? void 0 : onSwipe(e); + }, listenerOptions), + useEventListener(target, ["touchend", "touchcancel"], onTouchEnd, listenerOptions) + ]; + const stop = () => stops.forEach((s) => s()); + return { + isSwiping, + direction, + coordsStart, + coordsEnd, + lengthX: diffX, + lengthY: diffY, + stop, + // TODO: Remove in the next major version + isPassiveEventSupported: true + }; +} +function useTemplateRefsList() { + const refs = ref([]); + refs.value.set = (el) => { + if (el) + refs.value.push(el); + }; + onBeforeUpdate(() => { + refs.value.length = 0; + }); + return refs; +} +function useTextDirection(options = {}) { + const { + document: document2 = defaultDocument, + selector = "html", + observe = false, + initialValue = "ltr" + } = options; + function getValue2() { + var _a, _b; + return (_b = (_a = document2 == null ? void 0 : document2.querySelector(selector)) == null ? void 0 : _a.getAttribute("dir")) != null ? _b : initialValue; + } + const dir = ref(getValue2()); + tryOnMounted(() => dir.value = getValue2()); + if (observe && document2) { + useMutationObserver( + document2.querySelector(selector), + () => dir.value = getValue2(), + { attributes: true } + ); + } + return computed({ + get() { + return dir.value; + }, + set(v) { + var _a, _b; + dir.value = v; + if (!document2) + return; + if (dir.value) + (_a = document2.querySelector(selector)) == null ? void 0 : _a.setAttribute("dir", dir.value); + else + (_b = document2.querySelector(selector)) == null ? void 0 : _b.removeAttribute("dir"); + } + }); +} +function getRangesFromSelection(selection) { + var _a; + const rangeCount = (_a = selection.rangeCount) != null ? _a : 0; + return Array.from({ length: rangeCount }, (_, i) => selection.getRangeAt(i)); +} +function useTextSelection(options = {}) { + const { + window: window2 = defaultWindow + } = options; + const selection = ref(null); + const text = computed(() => { + var _a, _b; + return (_b = (_a = selection.value) == null ? void 0 : _a.toString()) != null ? _b : ""; + }); + const ranges = computed(() => selection.value ? getRangesFromSelection(selection.value) : []); + const rects = computed(() => ranges.value.map((range) => range.getBoundingClientRect())); + function onSelectionChange() { + selection.value = null; + if (window2) + selection.value = window2.getSelection(); + } + if (window2) + useEventListener(window2.document, "selectionchange", onSelectionChange, { passive: true }); + return { + text, + rects, + ranges, + selection + }; +} +function tryRequestAnimationFrame(window2 = defaultWindow, fn) { + if (window2 && typeof window2.requestAnimationFrame === "function") { + window2.requestAnimationFrame(fn); + } else { + fn(); + } +} +function useTextareaAutosize(options = {}) { + var _a, _b; + const { window: window2 = defaultWindow } = options; + const textarea = toRef2(options == null ? void 0 : options.element); + const input = toRef2((_a = options == null ? void 0 : options.input) != null ? _a : ""); + const styleProp = (_b = options == null ? void 0 : options.styleProp) != null ? _b : "height"; + const textareaScrollHeight = shallowRef(1); + const textareaOldWidth = shallowRef(0); + function triggerResize() { + var _a2; + if (!textarea.value) + return; + let height = ""; + textarea.value.style[styleProp] = "1px"; + textareaScrollHeight.value = (_a2 = textarea.value) == null ? void 0 : _a2.scrollHeight; + const _styleTarget = toValue(options == null ? void 0 : options.styleTarget); + if (_styleTarget) + _styleTarget.style[styleProp] = `${textareaScrollHeight.value}px`; + else + height = `${textareaScrollHeight.value}px`; + textarea.value.style[styleProp] = height; + } + watch([input, textarea], () => nextTick(triggerResize), { immediate: true }); + watch(textareaScrollHeight, () => { + var _a2; + return (_a2 = options == null ? void 0 : options.onResize) == null ? void 0 : _a2.call(options); + }); + useResizeObserver(textarea, ([{ contentRect }]) => { + if (textareaOldWidth.value === contentRect.width) + return; + tryRequestAnimationFrame(window2, () => { + textareaOldWidth.value = contentRect.width; + triggerResize(); + }); + }); + if (options == null ? void 0 : options.watch) + watch(options.watch, triggerResize, { immediate: true, deep: true }); + return { + textarea, + input, + triggerResize + }; +} +function useThrottledRefHistory(source, options = {}) { + const { throttle = 200, trailing = true } = options; + const filter = throttleFilter(throttle, trailing); + const history = useRefHistory(source, { ...options, eventFilter: filter }); + return { + ...history + }; +} +var DEFAULT_UNITS = [ + { max: 6e4, value: 1e3, name: "second" }, + { max: 276e4, value: 6e4, name: "minute" }, + { max: 72e6, value: 36e5, name: "hour" }, + { max: 5184e5, value: 864e5, name: "day" }, + { max: 24192e5, value: 6048e5, name: "week" }, + { max: 28512e6, value: 2592e6, name: "month" }, + { max: Number.POSITIVE_INFINITY, value: 31536e6, name: "year" } +]; +var DEFAULT_MESSAGES = { + justNow: "just now", + past: (n) => n.match(/\d/) ? `${n} ago` : n, + future: (n) => n.match(/\d/) ? `in ${n}` : n, + month: (n, past) => n === 1 ? past ? "last month" : "next month" : `${n} month${n > 1 ? "s" : ""}`, + year: (n, past) => n === 1 ? past ? "last year" : "next year" : `${n} year${n > 1 ? "s" : ""}`, + day: (n, past) => n === 1 ? past ? "yesterday" : "tomorrow" : `${n} day${n > 1 ? "s" : ""}`, + week: (n, past) => n === 1 ? past ? "last week" : "next week" : `${n} week${n > 1 ? "s" : ""}`, + hour: (n) => `${n} hour${n > 1 ? "s" : ""}`, + minute: (n) => `${n} minute${n > 1 ? "s" : ""}`, + second: (n) => `${n} second${n > 1 ? "s" : ""}`, + invalid: "" +}; +function DEFAULT_FORMATTER(date) { + return date.toISOString().slice(0, 10); +} +function useTimeAgo(time, options = {}) { + const { + controls: exposeControls = false, + updateInterval = 3e4 + } = options; + const { now: now2, ...controls } = useNow({ interval: updateInterval, controls: true }); + const timeAgo = computed(() => formatTimeAgo(new Date(toValue(time)), options, toValue(now2))); + if (exposeControls) { + return { + timeAgo, + ...controls + }; + } else { + return timeAgo; + } +} +function formatTimeAgo(from, options = {}, now2 = Date.now()) { + var _a; + const { + max, + messages = DEFAULT_MESSAGES, + fullDateFormatter = DEFAULT_FORMATTER, + units = DEFAULT_UNITS, + showSecond = false, + rounding = "round" + } = options; + const roundFn = typeof rounding === "number" ? (n) => +n.toFixed(rounding) : Math[rounding]; + const diff = +now2 - +from; + const absDiff = Math.abs(diff); + function getValue2(diff2, unit) { + return roundFn(Math.abs(diff2) / unit.value); + } + function format(diff2, unit) { + const val = getValue2(diff2, unit); + const past = diff2 > 0; + const str = applyFormat(unit.name, val, past); + return applyFormat(past ? "past" : "future", str, past); + } + function applyFormat(name, val, isPast) { + const formatter = messages[name]; + if (typeof formatter === "function") + return formatter(val, isPast); + return formatter.replace("{0}", val.toString()); + } + if (absDiff < 6e4 && !showSecond) + return messages.justNow; + if (typeof max === "number" && absDiff > max) + return fullDateFormatter(new Date(from)); + if (typeof max === "string") { + const unitMax = (_a = units.find((i) => i.name === max)) == null ? void 0 : _a.max; + if (unitMax && absDiff > unitMax) + return fullDateFormatter(new Date(from)); + } + for (const [idx, unit] of units.entries()) { + const val = getValue2(diff, unit); + if (val <= 0 && units[idx - 1]) + return format(diff, units[idx - 1]); + if (absDiff < unit.max) + return format(diff, unit); + } + return messages.invalid; +} +function useTimeoutPoll(fn, interval, options = {}) { + const { + immediate = true, + immediateCallback = false + } = options; + const { start } = useTimeoutFn(loop, interval, { immediate }); + const isActive = shallowRef(false); + async function loop() { + if (!isActive.value) + return; + await fn(); + start(); + } + function resume() { + if (!isActive.value) { + isActive.value = true; + if (immediateCallback) + fn(); + start(); + } + } + function pause() { + isActive.value = false; + } + if (immediate && isClient) + resume(); + tryOnScopeDispose(pause); + return { + isActive, + pause, + resume + }; +} +function useTimestamp(options = {}) { + const { + controls: exposeControls = false, + offset = 0, + immediate = true, + interval = "requestAnimationFrame", + callback + } = options; + const ts = shallowRef(timestamp() + offset); + const update = () => ts.value = timestamp() + offset; + const cb = callback ? () => { + update(); + callback(ts.value); + } : update; + const controls = interval === "requestAnimationFrame" ? useRafFn(cb, { immediate }) : useIntervalFn(cb, interval, { immediate }); + if (exposeControls) { + return { + timestamp: ts, + ...controls + }; + } else { + return ts; + } +} +function useTitle(newTitle = null, options = {}) { + var _a, _b, _c; + const { + document: document2 = defaultDocument, + restoreOnUnmount = (t) => t + } = options; + const originalTitle = (_a = document2 == null ? void 0 : document2.title) != null ? _a : ""; + const title = toRef2((_b = newTitle != null ? newTitle : document2 == null ? void 0 : document2.title) != null ? _b : null); + const isReadonly2 = !!(newTitle && typeof newTitle === "function"); + function format(t) { + if (!("titleTemplate" in options)) + return t; + const template = options.titleTemplate || "%s"; + return typeof template === "function" ? template(t) : toValue(template).replace(/%s/g, t); + } + watch( + title, + (newValue, oldValue) => { + if (newValue !== oldValue && document2) + document2.title = format(newValue != null ? newValue : ""); + }, + { immediate: true } + ); + if (options.observe && !options.titleTemplate && document2 && !isReadonly2) { + useMutationObserver( + (_c = document2.head) == null ? void 0 : _c.querySelector("title"), + () => { + if (document2 && document2.title !== title.value) + title.value = format(document2.title); + }, + { childList: true } + ); + } + tryOnScopeDispose(() => { + if (restoreOnUnmount) { + const restoredTitle = restoreOnUnmount(originalTitle, title.value || ""); + if (restoredTitle != null && document2) + document2.title = restoredTitle; + } + }); + return title; +} +var _TransitionPresets = { + easeInSine: [0.12, 0, 0.39, 0], + easeOutSine: [0.61, 1, 0.88, 1], + easeInOutSine: [0.37, 0, 0.63, 1], + easeInQuad: [0.11, 0, 0.5, 0], + easeOutQuad: [0.5, 1, 0.89, 1], + easeInOutQuad: [0.45, 0, 0.55, 1], + easeInCubic: [0.32, 0, 0.67, 0], + easeOutCubic: [0.33, 1, 0.68, 1], + easeInOutCubic: [0.65, 0, 0.35, 1], + easeInQuart: [0.5, 0, 0.75, 0], + easeOutQuart: [0.25, 1, 0.5, 1], + easeInOutQuart: [0.76, 0, 0.24, 1], + easeInQuint: [0.64, 0, 0.78, 0], + easeOutQuint: [0.22, 1, 0.36, 1], + easeInOutQuint: [0.83, 0, 0.17, 1], + easeInExpo: [0.7, 0, 0.84, 0], + easeOutExpo: [0.16, 1, 0.3, 1], + easeInOutExpo: [0.87, 0, 0.13, 1], + easeInCirc: [0.55, 0, 1, 0.45], + easeOutCirc: [0, 0.55, 0.45, 1], + easeInOutCirc: [0.85, 0, 0.15, 1], + easeInBack: [0.36, 0, 0.66, -0.56], + easeOutBack: [0.34, 1.56, 0.64, 1], + easeInOutBack: [0.68, -0.6, 0.32, 1.6] +}; +var TransitionPresets = Object.assign({}, { linear: identity }, _TransitionPresets); +function createEasingFunction([p0, p1, p2, p3]) { + const a = (a1, a2) => 1 - 3 * a2 + 3 * a1; + const b = (a1, a2) => 3 * a2 - 6 * a1; + const c = (a1) => 3 * a1; + const calcBezier = (t, a1, a2) => ((a(a1, a2) * t + b(a1, a2)) * t + c(a1)) * t; + const getSlope = (t, a1, a2) => 3 * a(a1, a2) * t * t + 2 * b(a1, a2) * t + c(a1); + const getTforX = (x) => { + let aGuessT = x; + for (let i = 0; i < 4; ++i) { + const currentSlope = getSlope(aGuessT, p0, p2); + if (currentSlope === 0) + return aGuessT; + const currentX = calcBezier(aGuessT, p0, p2) - x; + aGuessT -= currentX / currentSlope; + } + return aGuessT; + }; + return (x) => p0 === p1 && p2 === p3 ? x : calcBezier(getTforX(x), p1, p3); +} +function lerp(a, b, alpha) { + return a + alpha * (b - a); +} +function toVec(t) { + return (typeof t === "number" ? [t] : t) || []; +} +function executeTransition(source, from, to, options = {}) { + var _a, _b; + const fromVal = toValue(from); + const toVal = toValue(to); + const v1 = toVec(fromVal); + const v2 = toVec(toVal); + const duration = (_a = toValue(options.duration)) != null ? _a : 1e3; + const startedAt = Date.now(); + const endAt = Date.now() + duration; + const trans = typeof options.transition === "function" ? options.transition : (_b = toValue(options.transition)) != null ? _b : identity; + const ease = typeof trans === "function" ? trans : createEasingFunction(trans); + return new Promise((resolve) => { + source.value = fromVal; + const tick = () => { + var _a2; + if ((_a2 = options.abort) == null ? void 0 : _a2.call(options)) { + resolve(); + return; + } + const now2 = Date.now(); + const alpha = ease((now2 - startedAt) / duration); + const arr = toVec(source.value).map((n, i) => lerp(v1[i], v2[i], alpha)); + if (Array.isArray(source.value)) + source.value = arr.map((n, i) => { + var _a3, _b2; + return lerp((_a3 = v1[i]) != null ? _a3 : 0, (_b2 = v2[i]) != null ? _b2 : 0, alpha); + }); + else if (typeof source.value === "number") + source.value = arr[0]; + if (now2 < endAt) { + requestAnimationFrame(tick); + } else { + source.value = toVal; + resolve(); + } + }; + tick(); + }); +} +function useTransition(source, options = {}) { + let currentId = 0; + const sourceVal = () => { + const v = toValue(source); + return typeof v === "number" ? v : v.map(toValue); + }; + const outputRef = ref(sourceVal()); + watch(sourceVal, async (to) => { + var _a, _b; + if (toValue(options.disabled)) + return; + const id = ++currentId; + if (options.delay) + await promiseTimeout(toValue(options.delay)); + if (id !== currentId) + return; + const toVal = Array.isArray(to) ? to.map(toValue) : toValue(to); + (_a = options.onStarted) == null ? void 0 : _a.call(options); + await executeTransition(outputRef, outputRef.value, toVal, { + ...options, + abort: () => { + var _a2; + return id !== currentId || ((_a2 = options.abort) == null ? void 0 : _a2.call(options)); + } + }); + (_b = options.onFinished) == null ? void 0 : _b.call(options); + }, { deep: true }); + watch(() => toValue(options.disabled), (disabled) => { + if (disabled) { + currentId++; + outputRef.value = sourceVal(); + } + }); + tryOnScopeDispose(() => { + currentId++; + }); + return computed(() => toValue(options.disabled) ? sourceVal() : outputRef.value); +} +function useUrlSearchParams(mode = "history", options = {}) { + const { + initialValue = {}, + removeNullishValues = true, + removeFalsyValues = false, + write: enableWrite = true, + writeMode = "replace", + window: window2 = defaultWindow + } = options; + if (!window2) + return reactive(initialValue); + const state = reactive({}); + function getRawParams() { + if (mode === "history") { + return window2.location.search || ""; + } else if (mode === "hash") { + const hash = window2.location.hash || ""; + const index = hash.indexOf("?"); + return index > 0 ? hash.slice(index) : ""; + } else { + return (window2.location.hash || "").replace(/^#/, ""); + } + } + function constructQuery(params) { + const stringified = params.toString(); + if (mode === "history") + return `${stringified ? `?${stringified}` : ""}${window2.location.hash || ""}`; + if (mode === "hash-params") + return `${window2.location.search || ""}${stringified ? `#${stringified}` : ""}`; + const hash = window2.location.hash || "#"; + const index = hash.indexOf("?"); + if (index > 0) + return `${window2.location.search || ""}${hash.slice(0, index)}${stringified ? `?${stringified}` : ""}`; + return `${window2.location.search || ""}${hash}${stringified ? `?${stringified}` : ""}`; + } + function read() { + return new URLSearchParams(getRawParams()); + } + function updateState(params) { + const unusedKeys = new Set(Object.keys(state)); + for (const key of params.keys()) { + const paramsForKey = params.getAll(key); + state[key] = paramsForKey.length > 1 ? paramsForKey : params.get(key) || ""; + unusedKeys.delete(key); + } + Array.from(unusedKeys).forEach((key) => delete state[key]); + } + const { pause, resume } = watchPausable( + state, + () => { + const params = new URLSearchParams(""); + Object.keys(state).forEach((key) => { + const mapEntry = state[key]; + if (Array.isArray(mapEntry)) + mapEntry.forEach((value) => params.append(key, value)); + else if (removeNullishValues && mapEntry == null) + params.delete(key); + else if (removeFalsyValues && !mapEntry) + params.delete(key); + else + params.set(key, mapEntry); + }); + write(params, false); + }, + { deep: true } + ); + function write(params, shouldUpdate) { + pause(); + if (shouldUpdate) + updateState(params); + if (writeMode === "replace") { + window2.history.replaceState( + window2.history.state, + window2.document.title, + window2.location.pathname + constructQuery(params) + ); + } else { + window2.history.pushState( + window2.history.state, + window2.document.title, + window2.location.pathname + constructQuery(params) + ); + } + resume(); + } + function onChanged() { + if (!enableWrite) + return; + write(read(), true); + } + const listenerOptions = { passive: true }; + useEventListener(window2, "popstate", onChanged, listenerOptions); + if (mode !== "history") + useEventListener(window2, "hashchange", onChanged, listenerOptions); + const initial = read(); + if (initial.keys().next().value) + updateState(initial); + else + Object.assign(state, initialValue); + return state; +} +function useUserMedia(options = {}) { + var _a, _b; + const enabled = shallowRef((_a = options.enabled) != null ? _a : false); + const autoSwitch = shallowRef((_b = options.autoSwitch) != null ? _b : true); + const constraints = ref(options.constraints); + const { navigator: navigator2 = defaultNavigator } = options; + const isSupported = useSupported(() => { + var _a2; + return (_a2 = navigator2 == null ? void 0 : navigator2.mediaDevices) == null ? void 0 : _a2.getUserMedia; + }); + const stream = shallowRef(); + function getDeviceOptions(type) { + switch (type) { + case "video": { + if (constraints.value) + return constraints.value.video || false; + break; + } + case "audio": { + if (constraints.value) + return constraints.value.audio || false; + break; + } + } + } + async function _start() { + if (!isSupported.value || stream.value) + return; + stream.value = await navigator2.mediaDevices.getUserMedia({ + video: getDeviceOptions("video"), + audio: getDeviceOptions("audio") + }); + return stream.value; + } + function _stop() { + var _a2; + (_a2 = stream.value) == null ? void 0 : _a2.getTracks().forEach((t) => t.stop()); + stream.value = void 0; + } + function stop() { + _stop(); + enabled.value = false; + } + async function start() { + await _start(); + if (stream.value) + enabled.value = true; + return stream.value; + } + async function restart() { + _stop(); + return await start(); + } + watch( + enabled, + (v) => { + if (v) + _start(); + else _stop(); + }, + { immediate: true } + ); + watch( + constraints, + () => { + if (autoSwitch.value && stream.value) + restart(); + }, + { immediate: true } + ); + tryOnScopeDispose(() => { + stop(); + }); + return { + isSupported, + stream, + start, + stop, + restart, + constraints, + enabled, + autoSwitch + }; +} +function useVModel(props, key, emit, options = {}) { + var _a, _b, _c; + const { + clone = false, + passive = false, + eventName, + deep = false, + defaultValue, + shouldEmit + } = options; + const vm = getCurrentInstance(); + const _emit = emit || (vm == null ? void 0 : vm.emit) || ((_a = vm == null ? void 0 : vm.$emit) == null ? void 0 : _a.bind(vm)) || ((_c = (_b = vm == null ? void 0 : vm.proxy) == null ? void 0 : _b.$emit) == null ? void 0 : _c.bind(vm == null ? void 0 : vm.proxy)); + let event = eventName; + if (!key) { + key = "modelValue"; + } + event = event || `update:${key.toString()}`; + const cloneFn = (val) => !clone ? val : typeof clone === "function" ? clone(val) : cloneFnJSON(val); + const getValue2 = () => isDef(props[key]) ? cloneFn(props[key]) : defaultValue; + const triggerEmit = (value) => { + if (shouldEmit) { + if (shouldEmit(value)) + _emit(event, value); + } else { + _emit(event, value); + } + }; + if (passive) { + const initialValue = getValue2(); + const proxy = ref(initialValue); + let isUpdating = false; + watch( + () => props[key], + (v) => { + if (!isUpdating) { + isUpdating = true; + proxy.value = cloneFn(v); + nextTick(() => isUpdating = false); + } + } + ); + watch( + proxy, + (v) => { + if (!isUpdating && (v !== props[key] || deep)) + triggerEmit(v); + }, + { deep } + ); + return proxy; + } else { + return computed({ + get() { + return getValue2(); + }, + set(value) { + triggerEmit(value); + } + }); + } +} +function useVModels(props, emit, options = {}) { + const ret = {}; + for (const key in props) { + ret[key] = useVModel( + props, + key, + emit, + options + ); + } + return ret; +} +function useVibrate(options) { + const { + pattern = [], + interval = 0, + navigator: navigator2 = defaultNavigator + } = options || {}; + const isSupported = useSupported(() => typeof navigator2 !== "undefined" && "vibrate" in navigator2); + const patternRef = toRef2(pattern); + let intervalControls; + const vibrate = (pattern2 = patternRef.value) => { + if (isSupported.value) + navigator2.vibrate(pattern2); + }; + const stop = () => { + if (isSupported.value) + navigator2.vibrate(0); + intervalControls == null ? void 0 : intervalControls.pause(); + }; + if (interval > 0) { + intervalControls = useIntervalFn( + vibrate, + interval, + { + immediate: false, + immediateCallback: false + } + ); + } + return { + isSupported, + pattern, + intervalControls, + vibrate, + stop + }; +} +function useVirtualList(list, options) { + const { containerStyle, wrapperProps, scrollTo, calculateRange, currentList, containerRef } = "itemHeight" in options ? useVerticalVirtualList(options, list) : useHorizontalVirtualList(options, list); + return { + list: currentList, + scrollTo, + containerProps: { + ref: containerRef, + onScroll: () => { + calculateRange(); + }, + style: containerStyle + }, + wrapperProps + }; +} +function useVirtualListResources(list) { + const containerRef = shallowRef(null); + const size = useElementSize(containerRef); + const currentList = ref([]); + const source = shallowRef(list); + const state = ref({ start: 0, end: 10 }); + return { state, source, currentList, size, containerRef }; +} +function createGetViewCapacity(state, source, itemSize) { + return (containerSize) => { + if (typeof itemSize === "number") + return Math.ceil(containerSize / itemSize); + const { start = 0 } = state.value; + let sum = 0; + let capacity = 0; + for (let i = start; i < source.value.length; i++) { + const size = itemSize(i); + sum += size; + capacity = i; + if (sum > containerSize) + break; + } + return capacity - start; + }; +} +function createGetOffset(source, itemSize) { + return (scrollDirection) => { + if (typeof itemSize === "number") + return Math.floor(scrollDirection / itemSize) + 1; + let sum = 0; + let offset = 0; + for (let i = 0; i < source.value.length; i++) { + const size = itemSize(i); + sum += size; + if (sum >= scrollDirection) { + offset = i; + break; + } + } + return offset + 1; + }; +} +function createCalculateRange(type, overscan, getOffset, getViewCapacity, { containerRef, state, currentList, source }) { + return () => { + const element = containerRef.value; + if (element) { + const offset = getOffset(type === "vertical" ? element.scrollTop : element.scrollLeft); + const viewCapacity = getViewCapacity(type === "vertical" ? element.clientHeight : element.clientWidth); + const from = offset - overscan; + const to = offset + viewCapacity + overscan; + state.value = { + start: from < 0 ? 0 : from, + end: to > source.value.length ? source.value.length : to + }; + currentList.value = source.value.slice(state.value.start, state.value.end).map((ele, index) => ({ + data: ele, + index: index + state.value.start + })); + } + }; +} +function createGetDistance(itemSize, source) { + return (index) => { + if (typeof itemSize === "number") { + const size2 = index * itemSize; + return size2; + } + const size = source.value.slice(0, index).reduce((sum, _, i) => sum + itemSize(i), 0); + return size; + }; +} +function useWatchForSizes(size, list, containerRef, calculateRange) { + watch([size.width, size.height, list, containerRef], () => { + calculateRange(); + }); +} +function createComputedTotalSize(itemSize, source) { + return computed(() => { + if (typeof itemSize === "number") + return source.value.length * itemSize; + return source.value.reduce((sum, _, index) => sum + itemSize(index), 0); + }); +} +var scrollToDictionaryForElementScrollKey = { + horizontal: "scrollLeft", + vertical: "scrollTop" +}; +function createScrollTo(type, calculateRange, getDistance, containerRef) { + return (index) => { + if (containerRef.value) { + containerRef.value[scrollToDictionaryForElementScrollKey[type]] = getDistance(index); + calculateRange(); + } + }; +} +function useHorizontalVirtualList(options, list) { + const resources = useVirtualListResources(list); + const { state, source, currentList, size, containerRef } = resources; + const containerStyle = { overflowX: "auto" }; + const { itemWidth, overscan = 5 } = options; + const getViewCapacity = createGetViewCapacity(state, source, itemWidth); + const getOffset = createGetOffset(source, itemWidth); + const calculateRange = createCalculateRange("horizontal", overscan, getOffset, getViewCapacity, resources); + const getDistanceLeft = createGetDistance(itemWidth, source); + const offsetLeft = computed(() => getDistanceLeft(state.value.start)); + const totalWidth = createComputedTotalSize(itemWidth, source); + useWatchForSizes(size, list, containerRef, calculateRange); + const scrollTo = createScrollTo("horizontal", calculateRange, getDistanceLeft, containerRef); + const wrapperProps = computed(() => { + return { + style: { + height: "100%", + width: `${totalWidth.value - offsetLeft.value}px`, + marginLeft: `${offsetLeft.value}px`, + display: "flex" + } + }; + }); + return { + scrollTo, + calculateRange, + wrapperProps, + containerStyle, + currentList, + containerRef + }; +} +function useVerticalVirtualList(options, list) { + const resources = useVirtualListResources(list); + const { state, source, currentList, size, containerRef } = resources; + const containerStyle = { overflowY: "auto" }; + const { itemHeight, overscan = 5 } = options; + const getViewCapacity = createGetViewCapacity(state, source, itemHeight); + const getOffset = createGetOffset(source, itemHeight); + const calculateRange = createCalculateRange("vertical", overscan, getOffset, getViewCapacity, resources); + const getDistanceTop = createGetDistance(itemHeight, source); + const offsetTop = computed(() => getDistanceTop(state.value.start)); + const totalHeight = createComputedTotalSize(itemHeight, source); + useWatchForSizes(size, list, containerRef, calculateRange); + const scrollTo = createScrollTo("vertical", calculateRange, getDistanceTop, containerRef); + const wrapperProps = computed(() => { + return { + style: { + width: "100%", + height: `${totalHeight.value - offsetTop.value}px`, + marginTop: `${offsetTop.value}px` + } + }; + }); + return { + calculateRange, + scrollTo, + containerStyle, + wrapperProps, + currentList, + containerRef + }; +} +function useWakeLock(options = {}) { + const { + navigator: navigator2 = defaultNavigator, + document: document2 = defaultDocument + } = options; + const requestedType = shallowRef(false); + const sentinel = shallowRef(null); + const documentVisibility = useDocumentVisibility({ document: document2 }); + const isSupported = useSupported(() => navigator2 && "wakeLock" in navigator2); + const isActive = computed(() => !!sentinel.value && documentVisibility.value === "visible"); + if (isSupported.value) { + useEventListener(sentinel, "release", () => { + var _a, _b; + requestedType.value = (_b = (_a = sentinel.value) == null ? void 0 : _a.type) != null ? _b : false; + }, { passive: true }); + whenever( + () => documentVisibility.value === "visible" && (document2 == null ? void 0 : document2.visibilityState) === "visible" && requestedType.value, + (type) => { + requestedType.value = false; + forceRequest(type); + } + ); + } + async function forceRequest(type) { + var _a; + await ((_a = sentinel.value) == null ? void 0 : _a.release()); + sentinel.value = isSupported.value ? await navigator2.wakeLock.request(type) : null; + } + async function request(type) { + if (documentVisibility.value === "visible") + await forceRequest(type); + else + requestedType.value = type; + } + async function release() { + requestedType.value = false; + const s = sentinel.value; + sentinel.value = null; + await (s == null ? void 0 : s.release()); + } + return { + sentinel, + isSupported, + isActive, + request, + forceRequest, + release + }; +} +function useWebNotification(options = {}) { + const { + window: window2 = defaultWindow, + requestPermissions: _requestForPermissions = true + } = options; + const defaultWebNotificationOptions = options; + const isSupported = useSupported(() => { + if (!window2 || !("Notification" in window2)) + return false; + if (Notification.permission === "granted") + return true; + try { + const notification2 = new Notification(""); + notification2.onshow = () => { + notification2.close(); + }; + } catch (e) { + if (e.name === "TypeError") + return false; + } + return true; + }); + const permissionGranted = shallowRef(isSupported.value && "permission" in Notification && Notification.permission === "granted"); + const notification = ref(null); + const ensurePermissions = async () => { + if (!isSupported.value) + return; + if (!permissionGranted.value && Notification.permission !== "denied") { + const result = await Notification.requestPermission(); + if (result === "granted") + permissionGranted.value = true; + } + return permissionGranted.value; + }; + const { on: onClick, trigger: clickTrigger } = createEventHook(); + const { on: onShow, trigger: showTrigger } = createEventHook(); + const { on: onError, trigger: errorTrigger } = createEventHook(); + const { on: onClose, trigger: closeTrigger } = createEventHook(); + const show = async (overrides) => { + if (!isSupported.value || !permissionGranted.value) + return; + const options2 = Object.assign({}, defaultWebNotificationOptions, overrides); + notification.value = new Notification(options2.title || "", options2); + notification.value.onclick = clickTrigger; + notification.value.onshow = showTrigger; + notification.value.onerror = errorTrigger; + notification.value.onclose = closeTrigger; + return notification.value; + }; + const close = () => { + if (notification.value) + notification.value.close(); + notification.value = null; + }; + if (_requestForPermissions) + tryOnMounted(ensurePermissions); + tryOnScopeDispose(close); + if (isSupported.value && window2) { + const document2 = window2.document; + useEventListener(document2, "visibilitychange", (e) => { + e.preventDefault(); + if (document2.visibilityState === "visible") { + close(); + } + }); + } + return { + isSupported, + notification, + ensurePermissions, + permissionGranted, + show, + close, + onClick, + onShow, + onError, + onClose + }; +} +var DEFAULT_PING_MESSAGE = "ping"; +function resolveNestedOptions(options) { + if (options === true) + return {}; + return options; +} +function useWebSocket(url, options = {}) { + const { + onConnected, + onDisconnected, + onError, + onMessage, + immediate = true, + autoConnect = true, + autoClose = true, + protocols = [] + } = options; + const data = ref(null); + const status = shallowRef("CLOSED"); + const wsRef = ref(); + const urlRef = toRef2(url); + let heartbeatPause; + let heartbeatResume; + let explicitlyClosed = false; + let retried = 0; + let bufferedData = []; + let retryTimeout; + let pongTimeoutWait; + const _sendBuffer = () => { + if (bufferedData.length && wsRef.value && status.value === "OPEN") { + for (const buffer of bufferedData) + wsRef.value.send(buffer); + bufferedData = []; + } + }; + const resetRetry = () => { + if (retryTimeout != null) { + clearTimeout(retryTimeout); + retryTimeout = void 0; + } + }; + const resetHeartbeat = () => { + clearTimeout(pongTimeoutWait); + pongTimeoutWait = void 0; + }; + const close = (code = 1e3, reason) => { + resetRetry(); + if (!isClient && !isWorker || !wsRef.value) + return; + explicitlyClosed = true; + resetHeartbeat(); + heartbeatPause == null ? void 0 : heartbeatPause(); + wsRef.value.close(code, reason); + wsRef.value = void 0; + }; + const send = (data2, useBuffer = true) => { + if (!wsRef.value || status.value !== "OPEN") { + if (useBuffer) + bufferedData.push(data2); + return false; + } + _sendBuffer(); + wsRef.value.send(data2); + return true; + }; + const _init = () => { + if (explicitlyClosed || typeof urlRef.value === "undefined") + return; + const ws = new WebSocket(urlRef.value, protocols); + wsRef.value = ws; + status.value = "CONNECTING"; + ws.onopen = () => { + status.value = "OPEN"; + retried = 0; + onConnected == null ? void 0 : onConnected(ws); + heartbeatResume == null ? void 0 : heartbeatResume(); + _sendBuffer(); + }; + ws.onclose = (ev) => { + status.value = "CLOSED"; + resetHeartbeat(); + heartbeatPause == null ? void 0 : heartbeatPause(); + onDisconnected == null ? void 0 : onDisconnected(ws, ev); + if (!explicitlyClosed && options.autoReconnect && (wsRef.value == null || ws === wsRef.value)) { + const { + retries = -1, + delay = 1e3, + onFailed + } = resolveNestedOptions(options.autoReconnect); + const checkRetires = typeof retries === "function" ? retries : () => typeof retries === "number" && (retries < 0 || retried < retries); + if (checkRetires(retried)) { + retried += 1; + retryTimeout = setTimeout(_init, delay); + } else { + onFailed == null ? void 0 : onFailed(); + } + } + }; + ws.onerror = (e) => { + onError == null ? void 0 : onError(ws, e); + }; + ws.onmessage = (e) => { + if (options.heartbeat) { + resetHeartbeat(); + const { + message = DEFAULT_PING_MESSAGE, + responseMessage = message + } = resolveNestedOptions(options.heartbeat); + if (e.data === toValue(responseMessage)) + return; + } + data.value = e.data; + onMessage == null ? void 0 : onMessage(ws, e); + }; + }; + if (options.heartbeat) { + const { + message = DEFAULT_PING_MESSAGE, + interval = 1e3, + pongTimeout = 1e3 + } = resolveNestedOptions(options.heartbeat); + const { pause, resume } = useIntervalFn( + () => { + send(toValue(message), false); + if (pongTimeoutWait != null) + return; + pongTimeoutWait = setTimeout(() => { + close(); + explicitlyClosed = false; + }, pongTimeout); + }, + interval, + { immediate: false } + ); + heartbeatPause = pause; + heartbeatResume = resume; + } + if (autoClose) { + if (isClient) + useEventListener("beforeunload", () => close(), { passive: true }); + tryOnScopeDispose(close); + } + const open = () => { + if (!isClient && !isWorker) + return; + close(); + explicitlyClosed = false; + retried = 0; + _init(); + }; + if (immediate) + open(); + if (autoConnect) + watch(urlRef, open); + return { + data, + status, + close, + send, + open, + ws: wsRef + }; +} +function useWebWorker(arg0, workerOptions, options) { + const { + window: window2 = defaultWindow + } = options != null ? options : {}; + const data = ref(null); + const worker = shallowRef(); + const post = (...args) => { + if (!worker.value) + return; + worker.value.postMessage(...args); + }; + const terminate = function terminate2() { + if (!worker.value) + return; + worker.value.terminate(); + }; + if (window2) { + if (typeof arg0 === "string") + worker.value = new Worker(arg0, workerOptions); + else if (typeof arg0 === "function") + worker.value = arg0(); + else + worker.value = arg0; + worker.value.onmessage = (e) => { + data.value = e.data; + }; + tryOnScopeDispose(() => { + if (worker.value) + worker.value.terminate(); + }); + } + return { + data, + post, + terminate, + worker + }; +} +function depsParser(deps, localDeps) { + if (deps.length === 0 && localDeps.length === 0) + return ""; + const depsString = deps.map((dep) => `'${dep}'`).toString(); + const depsFunctionString = localDeps.filter((dep) => typeof dep === "function").map((fn) => { + const str = fn.toString(); + if (str.trim().startsWith("function")) { + return str; + } else { + const name = fn.name; + return `const ${name} = ${str}`; + } + }).join(";"); + const importString = `importScripts(${depsString});`; + return `${depsString.trim() === "" ? "" : importString} ${depsFunctionString}`; +} +function jobRunner(userFunc) { + return (e) => { + const userFuncArgs = e.data[0]; + return Promise.resolve(userFunc.apply(void 0, userFuncArgs)).then((result) => { + postMessage(["SUCCESS", result]); + }).catch((error) => { + postMessage(["ERROR", error]); + }); + }; +} +function createWorkerBlobUrl(fn, deps, localDeps) { + const blobCode = `${depsParser(deps, localDeps)}; onmessage=(${jobRunner})(${fn})`; + const blob = new Blob([blobCode], { type: "text/javascript" }); + const url = URL.createObjectURL(blob); + return url; +} +function useWebWorkerFn(fn, options = {}) { + const { + dependencies = [], + localDependencies = [], + timeout, + window: window2 = defaultWindow + } = options; + const worker = ref(); + const workerStatus = shallowRef("PENDING"); + const promise = ref({}); + const timeoutId = shallowRef(); + const workerTerminate = (status = "PENDING") => { + if (worker.value && worker.value._url && window2) { + worker.value.terminate(); + URL.revokeObjectURL(worker.value._url); + promise.value = {}; + worker.value = void 0; + window2.clearTimeout(timeoutId.value); + workerStatus.value = status; + } + }; + workerTerminate(); + tryOnScopeDispose(workerTerminate); + const generateWorker = () => { + const blobUrl = createWorkerBlobUrl(fn, dependencies, localDependencies); + const newWorker = new Worker(blobUrl); + newWorker._url = blobUrl; + newWorker.onmessage = (e) => { + const { resolve = () => { + }, reject = () => { + } } = promise.value; + const [status, result] = e.data; + switch (status) { + case "SUCCESS": + resolve(result); + workerTerminate(status); + break; + default: + reject(result); + workerTerminate("ERROR"); + break; + } + }; + newWorker.onerror = (e) => { + const { reject = () => { + } } = promise.value; + e.preventDefault(); + reject(e); + workerTerminate("ERROR"); + }; + if (timeout) { + timeoutId.value = setTimeout( + () => workerTerminate("TIMEOUT_EXPIRED"), + timeout + ); + } + return newWorker; + }; + const callWorker = (...fnArgs) => new Promise((resolve, reject) => { + var _a; + promise.value = { + resolve, + reject + }; + (_a = worker.value) == null ? void 0 : _a.postMessage([[...fnArgs]]); + workerStatus.value = "RUNNING"; + }); + const workerFn = (...fnArgs) => { + if (workerStatus.value === "RUNNING") { + console.error( + "[useWebWorkerFn] You can only run one instance of the worker at a time." + ); + return Promise.reject(); + } + worker.value = generateWorker(); + return callWorker(...fnArgs); + }; + return { + workerFn, + workerStatus, + workerTerminate + }; +} +function useWindowFocus(options = {}) { + const { window: window2 = defaultWindow } = options; + if (!window2) + return shallowRef(false); + const focused = shallowRef(window2.document.hasFocus()); + const listenerOptions = { passive: true }; + useEventListener(window2, "blur", () => { + focused.value = false; + }, listenerOptions); + useEventListener(window2, "focus", () => { + focused.value = true; + }, listenerOptions); + return focused; +} +function useWindowScroll(options = {}) { + const { window: window2 = defaultWindow, ...rest } = options; + return useScroll(window2, rest); +} +function useWindowSize(options = {}) { + const { + window: window2 = defaultWindow, + initialWidth = Number.POSITIVE_INFINITY, + initialHeight = Number.POSITIVE_INFINITY, + listenOrientation = true, + includeScrollbar = true, + type = "inner" + } = options; + const width = shallowRef(initialWidth); + const height = shallowRef(initialHeight); + const update = () => { + if (window2) { + if (type === "outer") { + width.value = window2.outerWidth; + height.value = window2.outerHeight; + } else if (type === "visual" && window2.visualViewport) { + const { width: visualViewportWidth, height: visualViewportHeight, scale } = window2.visualViewport; + width.value = Math.round(visualViewportWidth * scale); + height.value = Math.round(visualViewportHeight * scale); + } else if (includeScrollbar) { + width.value = window2.innerWidth; + height.value = window2.innerHeight; + } else { + width.value = window2.document.documentElement.clientWidth; + height.value = window2.document.documentElement.clientHeight; + } + } + }; + update(); + tryOnMounted(update); + const listenerOptions = { passive: true }; + useEventListener("resize", update, listenerOptions); + if (window2 && type === "visual" && window2.visualViewport) { + useEventListener(window2.visualViewport, "resize", update, listenerOptions); + } + if (listenOrientation) { + const matches = useMediaQuery("(orientation: portrait)"); + watch(matches, () => update()); + } + return { width, height }; +} + +export { + computedEager, + computedWithControl, + tryOnScopeDispose, + createEventHook, + createGlobalState, + injectLocal, + provideLocal, + createInjectionState, + createRef, + createSharedComposable, + extendRef, + get, + isDefined, + makeDestructurable, + reactify, + reactifyObject, + toReactive, + reactiveComputed, + reactiveOmit, + isClient, + isWorker, + isDef, + notNullish, + assert, + isObject, + now, + timestamp, + clamp, + noop, + rand, + hasOwn, + isIOS, + createFilterWrapper, + bypassFilter, + debounceFilter, + throttleFilter, + pausableFilter, + hyphenate, + camelize, + promiseTimeout, + identity, + createSingletonPromise, + invoke, + containsProp, + increaseWithUnit, + pxValue, + objectPick, + objectOmit, + objectEntries, + getLifeCycleTarget, + toArray, + toRef2 as toRef, + resolveRef, + reactivePick, + refAutoReset, + useDebounceFn, + refDebounced, + refDefault, + useThrottleFn, + refThrottled, + refWithControl, + controlledRef, + set, + watchWithFilter, + watchPausable, + syncRef, + syncRefs, + toRefs2 as toRefs, + toValue2 as toValue, + resolveUnref, + tryOnBeforeMount, + tryOnBeforeUnmount, + tryOnMounted, + tryOnUnmounted, + until, + useArrayDifference, + useArrayEvery, + useArrayFilter, + useArrayFind, + useArrayFindIndex, + useArrayFindLast, + useArrayIncludes, + useArrayJoin, + useArrayMap, + useArrayReduce, + useArraySome, + useArrayUnique, + useCounter, + formatDate, + normalizeDate, + useDateFormat, + useIntervalFn, + useInterval, + useLastChanged, + useTimeoutFn, + useTimeout, + useToNumber, + useToString, + useToggle, + watchArray, + watchAtMost, + watchDebounced, + watchDeep, + watchIgnorable, + watchImmediate, + watchOnce, + watchThrottled, + watchTriggerable, + whenever, + computedAsync, + computedInject, + createReusableTemplate, + createTemplatePromise, + createUnrefFn, + defaultWindow, + defaultDocument, + defaultNavigator, + defaultLocation, + unrefElement, + useEventListener, + onClickOutside, + useMounted, + useSupported, + useMutationObserver, + onElementRemoval, + onKeyStroke, + onKeyDown, + onKeyPressed, + onKeyUp, + onLongPress, + onStartTyping, + templateRef, + useActiveElement, + useRafFn, + useAnimate, + useAsyncQueue, + useAsyncState, + useBase64, + useBattery, + useBluetooth, + useSSRWidth, + provideSSRWidth, + useMediaQuery, + breakpointsTailwind, + breakpointsBootstrapV5, + breakpointsVuetifyV2, + breakpointsVuetifyV3, + breakpointsVuetify, + breakpointsAntDesign, + breakpointsQuasar, + breakpointsSematic, + breakpointsMasterCss, + breakpointsPrimeFlex, + breakpointsElement, + useBreakpoints, + useBroadcastChannel, + useBrowserLocation, + useCached, + usePermission, + useClipboard, + useClipboardItems, + cloneFnJSON, + useCloned, + getSSRHandler, + setSSRHandler, + usePreferredDark, + StorageSerializers, + customStorageEventName, + useStorage, + useColorMode, + useConfirmDialog, + useCountdown, + useCssVar, + useCurrentElement, + useCycleList, + useDark, + useManualRefHistory, + useRefHistory, + useDebouncedRefHistory, + useDeviceMotion, + useDeviceOrientation, + useDevicePixelRatio, + useDevicesList, + useDisplayMedia, + useDocumentVisibility, + useDraggable, + useDropZone, + useResizeObserver, + useElementBounding, + useElementByPoint, + useElementHover, + useElementSize, + useIntersectionObserver, + useElementVisibility, + useEventBus, + useEventSource, + useEyeDropper, + useFavicon, + createFetch, + useFetch, + useFileDialog, + useFileSystemAccess, + useFocus, + useFocusWithin, + useFps, + useFullscreen, + mapGamepadToXbox360Controller, + useGamepad, + useGeolocation, + useIdle, + useImage, + useScroll, + useInfiniteScroll, + useKeyModifier, + useLocalStorage, + DefaultMagicKeysAliasMap, + useMagicKeys, + useMediaControls, + useMemoize, + useMemory, + useMouse, + useMouseInElement, + useMousePressed, + useNavigatorLanguage, + useNetwork, + useNow, + useObjectUrl, + useOffsetPagination, + useOnline, + usePageLeave, + useScreenOrientation, + useParallax, + useParentElement, + usePerformanceObserver, + usePointer, + usePointerLock, + usePointerSwipe, + usePreferredColorScheme, + usePreferredContrast, + usePreferredLanguages, + usePreferredReducedMotion, + usePreferredReducedTransparency, + usePrevious, + useScreenSafeArea, + useScriptTag, + useScrollLock, + useSessionStorage, + useShare, + useSorted, + useSpeechRecognition, + useSpeechSynthesis, + useStepper, + useStorageAsync, + useStyleTag, + useSwipe, + useTemplateRefsList, + useTextDirection, + useTextSelection, + useTextareaAutosize, + useThrottledRefHistory, + useTimeAgo, + formatTimeAgo, + useTimeoutPoll, + useTimestamp, + useTitle, + TransitionPresets, + executeTransition, + useTransition, + useUrlSearchParams, + useUserMedia, + useVModel, + useVModels, + useVibrate, + useVirtualList, + useWakeLock, + useWebNotification, + useWebSocket, + useWebWorker, + useWebWorkerFn, + useWindowFocus, + useWindowScroll, + useWindowSize +}; +//# sourceMappingURL=chunk-2CLQ7TTZ.js.map diff --git a/docs/.vitepress/cache/deps/chunk-2CLQ7TTZ.js.map b/docs/.vitepress/cache/deps/chunk-2CLQ7TTZ.js.map new file mode 100644 index 0000000..64aea30 --- /dev/null +++ b/docs/.vitepress/cache/deps/chunk-2CLQ7TTZ.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../../../../node_modules/@vueuse/shared/index.mjs", "../../../../node_modules/@vueuse/core/index.mjs"], + "sourcesContent": ["import { shallowRef, watchEffect, readonly, watch, customRef, getCurrentScope, onScopeDispose, effectScope, getCurrentInstance, hasInjectionContext, inject, provide, ref, isRef, unref, toValue as toValue$1, computed, reactive, toRefs as toRefs$1, toRef as toRef$1, onBeforeMount, nextTick, onBeforeUnmount, onMounted, onUnmounted, isReactive } from 'vue';\n\nfunction computedEager(fn, options) {\n var _a;\n const result = shallowRef();\n watchEffect(() => {\n result.value = fn();\n }, {\n ...options,\n flush: (_a = options == null ? void 0 : options.flush) != null ? _a : \"sync\"\n });\n return readonly(result);\n}\n\nfunction computedWithControl(source, fn) {\n let v = void 0;\n let track;\n let trigger;\n const dirty = shallowRef(true);\n const update = () => {\n dirty.value = true;\n trigger();\n };\n watch(source, update, { flush: \"sync\" });\n const get = typeof fn === \"function\" ? fn : fn.get;\n const set = typeof fn === \"function\" ? void 0 : fn.set;\n const result = customRef((_track, _trigger) => {\n track = _track;\n trigger = _trigger;\n return {\n get() {\n if (dirty.value) {\n v = get(v);\n dirty.value = false;\n }\n track();\n return v;\n },\n set(v2) {\n set == null ? void 0 : set(v2);\n }\n };\n });\n if (Object.isExtensible(result))\n result.trigger = update;\n return result;\n}\n\nfunction tryOnScopeDispose(fn) {\n if (getCurrentScope()) {\n onScopeDispose(fn);\n return true;\n }\n return false;\n}\n\nfunction createEventHook() {\n const fns = /* @__PURE__ */ new Set();\n const off = (fn) => {\n fns.delete(fn);\n };\n const clear = () => {\n fns.clear();\n };\n const on = (fn) => {\n fns.add(fn);\n const offFn = () => off(fn);\n tryOnScopeDispose(offFn);\n return {\n off: offFn\n };\n };\n const trigger = (...args) => {\n return Promise.all(Array.from(fns).map((fn) => fn(...args)));\n };\n return {\n on,\n off,\n trigger,\n clear\n };\n}\n\nfunction createGlobalState(stateFactory) {\n let initialized = false;\n let state;\n const scope = effectScope(true);\n return (...args) => {\n if (!initialized) {\n state = scope.run(() => stateFactory(...args));\n initialized = true;\n }\n return state;\n };\n}\n\nconst localProvidedStateMap = /* @__PURE__ */ new WeakMap();\n\nconst injectLocal = (...args) => {\n var _a;\n const key = args[0];\n const instance = (_a = getCurrentInstance()) == null ? void 0 : _a.proxy;\n if (instance == null && !hasInjectionContext())\n throw new Error(\"injectLocal must be called in setup\");\n if (instance && localProvidedStateMap.has(instance) && key in localProvidedStateMap.get(instance))\n return localProvidedStateMap.get(instance)[key];\n return inject(...args);\n};\n\nconst provideLocal = (key, value) => {\n var _a;\n const instance = (_a = getCurrentInstance()) == null ? void 0 : _a.proxy;\n if (instance == null)\n throw new Error(\"provideLocal must be called in setup\");\n if (!localProvidedStateMap.has(instance))\n localProvidedStateMap.set(instance, /* @__PURE__ */ Object.create(null));\n const localProvidedState = localProvidedStateMap.get(instance);\n localProvidedState[key] = value;\n provide(key, value);\n};\n\nfunction createInjectionState(composable, options) {\n const key = (options == null ? void 0 : options.injectionKey) || Symbol(composable.name || \"InjectionState\");\n const defaultValue = options == null ? void 0 : options.defaultValue;\n const useProvidingState = (...args) => {\n const state = composable(...args);\n provideLocal(key, state);\n return state;\n };\n const useInjectedState = () => injectLocal(key, defaultValue);\n return [useProvidingState, useInjectedState];\n}\n\nfunction createRef(value, deep) {\n if (deep === true) {\n return ref(value);\n } else {\n return shallowRef(value);\n }\n}\n\nfunction createSharedComposable(composable) {\n let subscribers = 0;\n let state;\n let scope;\n const dispose = () => {\n subscribers -= 1;\n if (scope && subscribers <= 0) {\n scope.stop();\n state = void 0;\n scope = void 0;\n }\n };\n return (...args) => {\n subscribers += 1;\n if (!scope) {\n scope = effectScope(true);\n state = scope.run(() => composable(...args));\n }\n tryOnScopeDispose(dispose);\n return state;\n };\n}\n\nfunction extendRef(ref, extend, { enumerable = false, unwrap = true } = {}) {\n for (const [key, value] of Object.entries(extend)) {\n if (key === \"value\")\n continue;\n if (isRef(value) && unwrap) {\n Object.defineProperty(ref, key, {\n get() {\n return value.value;\n },\n set(v) {\n value.value = v;\n },\n enumerable\n });\n } else {\n Object.defineProperty(ref, key, { value, enumerable });\n }\n }\n return ref;\n}\n\nfunction get(obj, key) {\n if (key == null)\n return unref(obj);\n return unref(obj)[key];\n}\n\nfunction isDefined(v) {\n return unref(v) != null;\n}\n\nfunction makeDestructurable(obj, arr) {\n if (typeof Symbol !== \"undefined\") {\n const clone = { ...obj };\n Object.defineProperty(clone, Symbol.iterator, {\n enumerable: false,\n value() {\n let index = 0;\n return {\n next: () => ({\n value: arr[index++],\n done: index > arr.length\n })\n };\n }\n });\n return clone;\n } else {\n return Object.assign([...arr], obj);\n }\n}\n\nfunction reactify(fn, options) {\n const unrefFn = (options == null ? void 0 : options.computedGetter) === false ? unref : toValue$1;\n return function(...args) {\n return computed(() => fn.apply(this, args.map((i) => unrefFn(i))));\n };\n}\n\nfunction reactifyObject(obj, optionsOrKeys = {}) {\n let keys = [];\n let options;\n if (Array.isArray(optionsOrKeys)) {\n keys = optionsOrKeys;\n } else {\n options = optionsOrKeys;\n const { includeOwnProperties = true } = optionsOrKeys;\n keys.push(...Object.keys(obj));\n if (includeOwnProperties)\n keys.push(...Object.getOwnPropertyNames(obj));\n }\n return Object.fromEntries(\n keys.map((key) => {\n const value = obj[key];\n return [\n key,\n typeof value === \"function\" ? reactify(value.bind(obj), options) : value\n ];\n })\n );\n}\n\nfunction toReactive(objectRef) {\n if (!isRef(objectRef))\n return reactive(objectRef);\n const proxy = new Proxy({}, {\n get(_, p, receiver) {\n return unref(Reflect.get(objectRef.value, p, receiver));\n },\n set(_, p, value) {\n if (isRef(objectRef.value[p]) && !isRef(value))\n objectRef.value[p].value = value;\n else\n objectRef.value[p] = value;\n return true;\n },\n deleteProperty(_, p) {\n return Reflect.deleteProperty(objectRef.value, p);\n },\n has(_, p) {\n return Reflect.has(objectRef.value, p);\n },\n ownKeys() {\n return Object.keys(objectRef.value);\n },\n getOwnPropertyDescriptor() {\n return {\n enumerable: true,\n configurable: true\n };\n }\n });\n return reactive(proxy);\n}\n\nfunction reactiveComputed(fn) {\n return toReactive(computed(fn));\n}\n\nfunction reactiveOmit(obj, ...keys) {\n const flatKeys = keys.flat();\n const predicate = flatKeys[0];\n return reactiveComputed(() => typeof predicate === \"function\" ? Object.fromEntries(Object.entries(toRefs$1(obj)).filter(([k, v]) => !predicate(toValue$1(v), k))) : Object.fromEntries(Object.entries(toRefs$1(obj)).filter((e) => !flatKeys.includes(e[0]))));\n}\n\nconst isClient = typeof window !== \"undefined\" && typeof document !== \"undefined\";\nconst isWorker = typeof WorkerGlobalScope !== \"undefined\" && globalThis instanceof WorkerGlobalScope;\nconst isDef = (val) => typeof val !== \"undefined\";\nconst notNullish = (val) => val != null;\nconst assert = (condition, ...infos) => {\n if (!condition)\n console.warn(...infos);\n};\nconst toString = Object.prototype.toString;\nconst isObject = (val) => toString.call(val) === \"[object Object]\";\nconst now = () => Date.now();\nconst timestamp = () => +Date.now();\nconst clamp = (n, min, max) => Math.min(max, Math.max(min, n));\nconst noop = () => {\n};\nconst rand = (min, max) => {\n min = Math.ceil(min);\n max = Math.floor(max);\n return Math.floor(Math.random() * (max - min + 1)) + min;\n};\nconst hasOwn = (val, key) => Object.prototype.hasOwnProperty.call(val, key);\nconst isIOS = /* @__PURE__ */ getIsIOS();\nfunction getIsIOS() {\n var _a, _b;\n return isClient && ((_a = window == null ? void 0 : window.navigator) == null ? void 0 : _a.userAgent) && (/iP(?:ad|hone|od)/.test(window.navigator.userAgent) || ((_b = window == null ? void 0 : window.navigator) == null ? void 0 : _b.maxTouchPoints) > 2 && /iPad|Macintosh/.test(window == null ? void 0 : window.navigator.userAgent));\n}\n\nfunction createFilterWrapper(filter, fn) {\n function wrapper(...args) {\n return new Promise((resolve, reject) => {\n Promise.resolve(filter(() => fn.apply(this, args), { fn, thisArg: this, args })).then(resolve).catch(reject);\n });\n }\n return wrapper;\n}\nconst bypassFilter = (invoke) => {\n return invoke();\n};\nfunction debounceFilter(ms, options = {}) {\n let timer;\n let maxTimer;\n let lastRejector = noop;\n const _clearTimeout = (timer2) => {\n clearTimeout(timer2);\n lastRejector();\n lastRejector = noop;\n };\n let lastInvoker;\n const filter = (invoke) => {\n const duration = toValue$1(ms);\n const maxDuration = toValue$1(options.maxWait);\n if (timer)\n _clearTimeout(timer);\n if (duration <= 0 || maxDuration !== void 0 && maxDuration <= 0) {\n if (maxTimer) {\n _clearTimeout(maxTimer);\n maxTimer = null;\n }\n return Promise.resolve(invoke());\n }\n return new Promise((resolve, reject) => {\n lastRejector = options.rejectOnCancel ? reject : resolve;\n lastInvoker = invoke;\n if (maxDuration && !maxTimer) {\n maxTimer = setTimeout(() => {\n if (timer)\n _clearTimeout(timer);\n maxTimer = null;\n resolve(lastInvoker());\n }, maxDuration);\n }\n timer = setTimeout(() => {\n if (maxTimer)\n _clearTimeout(maxTimer);\n maxTimer = null;\n resolve(invoke());\n }, duration);\n });\n };\n return filter;\n}\nfunction throttleFilter(...args) {\n let lastExec = 0;\n let timer;\n let isLeading = true;\n let lastRejector = noop;\n let lastValue;\n let ms;\n let trailing;\n let leading;\n let rejectOnCancel;\n if (!isRef(args[0]) && typeof args[0] === \"object\")\n ({ delay: ms, trailing = true, leading = true, rejectOnCancel = false } = args[0]);\n else\n [ms, trailing = true, leading = true, rejectOnCancel = false] = args;\n const clear = () => {\n if (timer) {\n clearTimeout(timer);\n timer = void 0;\n lastRejector();\n lastRejector = noop;\n }\n };\n const filter = (_invoke) => {\n const duration = toValue$1(ms);\n const elapsed = Date.now() - lastExec;\n const invoke = () => {\n return lastValue = _invoke();\n };\n clear();\n if (duration <= 0) {\n lastExec = Date.now();\n return invoke();\n }\n if (elapsed > duration && (leading || !isLeading)) {\n lastExec = Date.now();\n invoke();\n } else if (trailing) {\n lastValue = new Promise((resolve, reject) => {\n lastRejector = rejectOnCancel ? reject : resolve;\n timer = setTimeout(() => {\n lastExec = Date.now();\n isLeading = true;\n resolve(invoke());\n clear();\n }, Math.max(0, duration - elapsed));\n });\n }\n if (!leading && !timer)\n timer = setTimeout(() => isLeading = true, duration);\n isLeading = false;\n return lastValue;\n };\n return filter;\n}\nfunction pausableFilter(extendFilter = bypassFilter, options = {}) {\n const {\n initialState = \"active\"\n } = options;\n const isActive = toRef(initialState === \"active\");\n function pause() {\n isActive.value = false;\n }\n function resume() {\n isActive.value = true;\n }\n const eventFilter = (...args) => {\n if (isActive.value)\n extendFilter(...args);\n };\n return { isActive: readonly(isActive), pause, resume, eventFilter };\n}\n\nfunction cacheStringFunction(fn) {\n const cache = /* @__PURE__ */ Object.create(null);\n return (str) => {\n const hit = cache[str];\n return hit || (cache[str] = fn(str));\n };\n}\nconst hyphenateRE = /\\B([A-Z])/g;\nconst hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, \"-$1\").toLowerCase());\nconst camelizeRE = /-(\\w)/g;\nconst camelize = cacheStringFunction((str) => {\n return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : \"\");\n});\n\nfunction promiseTimeout(ms, throwOnTimeout = false, reason = \"Timeout\") {\n return new Promise((resolve, reject) => {\n if (throwOnTimeout)\n setTimeout(() => reject(reason), ms);\n else\n setTimeout(resolve, ms);\n });\n}\nfunction identity(arg) {\n return arg;\n}\nfunction createSingletonPromise(fn) {\n let _promise;\n function wrapper() {\n if (!_promise)\n _promise = fn();\n return _promise;\n }\n wrapper.reset = async () => {\n const _prev = _promise;\n _promise = void 0;\n if (_prev)\n await _prev;\n };\n return wrapper;\n}\nfunction invoke(fn) {\n return fn();\n}\nfunction containsProp(obj, ...props) {\n return props.some((k) => k in obj);\n}\nfunction increaseWithUnit(target, delta) {\n var _a;\n if (typeof target === \"number\")\n return target + delta;\n const value = ((_a = target.match(/^-?\\d+\\.?\\d*/)) == null ? void 0 : _a[0]) || \"\";\n const unit = target.slice(value.length);\n const result = Number.parseFloat(value) + delta;\n if (Number.isNaN(result))\n return target;\n return result + unit;\n}\nfunction pxValue(px) {\n return px.endsWith(\"rem\") ? Number.parseFloat(px) * 16 : Number.parseFloat(px);\n}\nfunction objectPick(obj, keys, omitUndefined = false) {\n return keys.reduce((n, k) => {\n if (k in obj) {\n if (!omitUndefined || obj[k] !== void 0)\n n[k] = obj[k];\n }\n return n;\n }, {});\n}\nfunction objectOmit(obj, keys, omitUndefined = false) {\n return Object.fromEntries(Object.entries(obj).filter(([key, value]) => {\n return (!omitUndefined || value !== void 0) && !keys.includes(key);\n }));\n}\nfunction objectEntries(obj) {\n return Object.entries(obj);\n}\nfunction getLifeCycleTarget(target) {\n return target || getCurrentInstance();\n}\nfunction toArray(value) {\n return Array.isArray(value) ? value : [value];\n}\n\nfunction toRef(...args) {\n if (args.length !== 1)\n return toRef$1(...args);\n const r = args[0];\n return typeof r === \"function\" ? readonly(customRef(() => ({ get: r, set: noop }))) : ref(r);\n}\nconst resolveRef = toRef;\n\nfunction reactivePick(obj, ...keys) {\n const flatKeys = keys.flat();\n const predicate = flatKeys[0];\n return reactiveComputed(() => typeof predicate === \"function\" ? Object.fromEntries(Object.entries(toRefs$1(obj)).filter(([k, v]) => predicate(toValue$1(v), k))) : Object.fromEntries(flatKeys.map((k) => [k, toRef(obj, k)])));\n}\n\nfunction refAutoReset(defaultValue, afterMs = 1e4) {\n return customRef((track, trigger) => {\n let value = toValue$1(defaultValue);\n let timer;\n const resetAfter = () => setTimeout(() => {\n value = toValue$1(defaultValue);\n trigger();\n }, toValue$1(afterMs));\n tryOnScopeDispose(() => {\n clearTimeout(timer);\n });\n return {\n get() {\n track();\n return value;\n },\n set(newValue) {\n value = newValue;\n trigger();\n clearTimeout(timer);\n timer = resetAfter();\n }\n };\n });\n}\n\nfunction useDebounceFn(fn, ms = 200, options = {}) {\n return createFilterWrapper(\n debounceFilter(ms, options),\n fn\n );\n}\n\nfunction refDebounced(value, ms = 200, options = {}) {\n const debounced = ref(value.value);\n const updater = useDebounceFn(() => {\n debounced.value = value.value;\n }, ms, options);\n watch(value, () => updater());\n return debounced;\n}\n\nfunction refDefault(source, defaultValue) {\n return computed({\n get() {\n var _a;\n return (_a = source.value) != null ? _a : defaultValue;\n },\n set(value) {\n source.value = value;\n }\n });\n}\n\nfunction useThrottleFn(fn, ms = 200, trailing = false, leading = true, rejectOnCancel = false) {\n return createFilterWrapper(\n throttleFilter(ms, trailing, leading, rejectOnCancel),\n fn\n );\n}\n\nfunction refThrottled(value, delay = 200, trailing = true, leading = true) {\n if (delay <= 0)\n return value;\n const throttled = ref(value.value);\n const updater = useThrottleFn(() => {\n throttled.value = value.value;\n }, delay, trailing, leading);\n watch(value, () => updater());\n return throttled;\n}\n\nfunction refWithControl(initial, options = {}) {\n let source = initial;\n let track;\n let trigger;\n const ref = customRef((_track, _trigger) => {\n track = _track;\n trigger = _trigger;\n return {\n get() {\n return get();\n },\n set(v) {\n set(v);\n }\n };\n });\n function get(tracking = true) {\n if (tracking)\n track();\n return source;\n }\n function set(value, triggering = true) {\n var _a, _b;\n if (value === source)\n return;\n const old = source;\n if (((_a = options.onBeforeChange) == null ? void 0 : _a.call(options, value, old)) === false)\n return;\n source = value;\n (_b = options.onChanged) == null ? void 0 : _b.call(options, value, old);\n if (triggering)\n trigger();\n }\n const untrackedGet = () => get(false);\n const silentSet = (v) => set(v, false);\n const peek = () => get(false);\n const lay = (v) => set(v, false);\n return extendRef(\n ref,\n {\n get,\n set,\n untrackedGet,\n silentSet,\n peek,\n lay\n },\n { enumerable: true }\n );\n}\nconst controlledRef = refWithControl;\n\nfunction set(...args) {\n if (args.length === 2) {\n const [ref, value] = args;\n ref.value = value;\n }\n if (args.length === 3) {\n const [target, key, value] = args;\n target[key] = value;\n }\n}\n\nfunction watchWithFilter(source, cb, options = {}) {\n const {\n eventFilter = bypassFilter,\n ...watchOptions\n } = options;\n return watch(\n source,\n createFilterWrapper(\n eventFilter,\n cb\n ),\n watchOptions\n );\n}\n\nfunction watchPausable(source, cb, options = {}) {\n const {\n eventFilter: filter,\n initialState = \"active\",\n ...watchOptions\n } = options;\n const { eventFilter, pause, resume, isActive } = pausableFilter(filter, { initialState });\n const stop = watchWithFilter(\n source,\n cb,\n {\n ...watchOptions,\n eventFilter\n }\n );\n return { stop, pause, resume, isActive };\n}\n\nfunction syncRef(left, right, ...[options]) {\n const {\n flush = \"sync\",\n deep = false,\n immediate = true,\n direction = \"both\",\n transform = {}\n } = options || {};\n const watchers = [];\n const transformLTR = \"ltr\" in transform && transform.ltr || ((v) => v);\n const transformRTL = \"rtl\" in transform && transform.rtl || ((v) => v);\n if (direction === \"both\" || direction === \"ltr\") {\n watchers.push(watchPausable(\n left,\n (newValue) => {\n watchers.forEach((w) => w.pause());\n right.value = transformLTR(newValue);\n watchers.forEach((w) => w.resume());\n },\n { flush, deep, immediate }\n ));\n }\n if (direction === \"both\" || direction === \"rtl\") {\n watchers.push(watchPausable(\n right,\n (newValue) => {\n watchers.forEach((w) => w.pause());\n left.value = transformRTL(newValue);\n watchers.forEach((w) => w.resume());\n },\n { flush, deep, immediate }\n ));\n }\n const stop = () => {\n watchers.forEach((w) => w.stop());\n };\n return stop;\n}\n\nfunction syncRefs(source, targets, options = {}) {\n const {\n flush = \"sync\",\n deep = false,\n immediate = true\n } = options;\n const targetsArray = toArray(targets);\n return watch(\n source,\n (newValue) => targetsArray.forEach((target) => target.value = newValue),\n { flush, deep, immediate }\n );\n}\n\nfunction toRefs(objectRef, options = {}) {\n if (!isRef(objectRef))\n return toRefs$1(objectRef);\n const result = Array.isArray(objectRef.value) ? Array.from({ length: objectRef.value.length }) : {};\n for (const key in objectRef.value) {\n result[key] = customRef(() => ({\n get() {\n return objectRef.value[key];\n },\n set(v) {\n var _a;\n const replaceRef = (_a = toValue$1(options.replaceRef)) != null ? _a : true;\n if (replaceRef) {\n if (Array.isArray(objectRef.value)) {\n const copy = [...objectRef.value];\n copy[key] = v;\n objectRef.value = copy;\n } else {\n const newObject = { ...objectRef.value, [key]: v };\n Object.setPrototypeOf(newObject, Object.getPrototypeOf(objectRef.value));\n objectRef.value = newObject;\n }\n } else {\n objectRef.value[key] = v;\n }\n }\n }));\n }\n return result;\n}\n\nconst toValue = toValue$1;\nconst resolveUnref = toValue$1;\n\nfunction tryOnBeforeMount(fn, sync = true, target) {\n const instance = getLifeCycleTarget(target);\n if (instance)\n onBeforeMount(fn, target);\n else if (sync)\n fn();\n else\n nextTick(fn);\n}\n\nfunction tryOnBeforeUnmount(fn, target) {\n const instance = getLifeCycleTarget(target);\n if (instance)\n onBeforeUnmount(fn, target);\n}\n\nfunction tryOnMounted(fn, sync = true, target) {\n const instance = getLifeCycleTarget();\n if (instance)\n onMounted(fn, target);\n else if (sync)\n fn();\n else\n nextTick(fn);\n}\n\nfunction tryOnUnmounted(fn, target) {\n const instance = getLifeCycleTarget(target);\n if (instance)\n onUnmounted(fn, target);\n}\n\nfunction createUntil(r, isNot = false) {\n function toMatch(condition, { flush = \"sync\", deep = false, timeout, throwOnTimeout } = {}) {\n let stop = null;\n const watcher = new Promise((resolve) => {\n stop = watch(\n r,\n (v) => {\n if (condition(v) !== isNot) {\n if (stop)\n stop();\n else\n nextTick(() => stop == null ? void 0 : stop());\n resolve(v);\n }\n },\n {\n flush,\n deep,\n immediate: true\n }\n );\n });\n const promises = [watcher];\n if (timeout != null) {\n promises.push(\n promiseTimeout(timeout, throwOnTimeout).then(() => toValue$1(r)).finally(() => stop == null ? void 0 : stop())\n );\n }\n return Promise.race(promises);\n }\n function toBe(value, options) {\n if (!isRef(value))\n return toMatch((v) => v === value, options);\n const { flush = \"sync\", deep = false, timeout, throwOnTimeout } = options != null ? options : {};\n let stop = null;\n const watcher = new Promise((resolve) => {\n stop = watch(\n [r, value],\n ([v1, v2]) => {\n if (isNot !== (v1 === v2)) {\n if (stop)\n stop();\n else\n nextTick(() => stop == null ? void 0 : stop());\n resolve(v1);\n }\n },\n {\n flush,\n deep,\n immediate: true\n }\n );\n });\n const promises = [watcher];\n if (timeout != null) {\n promises.push(\n promiseTimeout(timeout, throwOnTimeout).then(() => toValue$1(r)).finally(() => {\n stop == null ? void 0 : stop();\n return toValue$1(r);\n })\n );\n }\n return Promise.race(promises);\n }\n function toBeTruthy(options) {\n return toMatch((v) => Boolean(v), options);\n }\n function toBeNull(options) {\n return toBe(null, options);\n }\n function toBeUndefined(options) {\n return toBe(void 0, options);\n }\n function toBeNaN(options) {\n return toMatch(Number.isNaN, options);\n }\n function toContains(value, options) {\n return toMatch((v) => {\n const array = Array.from(v);\n return array.includes(value) || array.includes(toValue$1(value));\n }, options);\n }\n function changed(options) {\n return changedTimes(1, options);\n }\n function changedTimes(n = 1, options) {\n let count = -1;\n return toMatch(() => {\n count += 1;\n return count >= n;\n }, options);\n }\n if (Array.isArray(toValue$1(r))) {\n const instance = {\n toMatch,\n toContains,\n changed,\n changedTimes,\n get not() {\n return createUntil(r, !isNot);\n }\n };\n return instance;\n } else {\n const instance = {\n toMatch,\n toBe,\n toBeTruthy,\n toBeNull,\n toBeNaN,\n toBeUndefined,\n changed,\n changedTimes,\n get not() {\n return createUntil(r, !isNot);\n }\n };\n return instance;\n }\n}\nfunction until(r) {\n return createUntil(r);\n}\n\nfunction defaultComparator(value, othVal) {\n return value === othVal;\n}\nfunction useArrayDifference(...args) {\n var _a, _b;\n const list = args[0];\n const values = args[1];\n let compareFn = (_a = args[2]) != null ? _a : defaultComparator;\n const {\n symmetric = false\n } = (_b = args[3]) != null ? _b : {};\n if (typeof compareFn === \"string\") {\n const key = compareFn;\n compareFn = (value, othVal) => value[key] === othVal[key];\n }\n const diff1 = computed(() => toValue$1(list).filter((x) => toValue$1(values).findIndex((y) => compareFn(x, y)) === -1));\n if (symmetric) {\n const diff2 = computed(() => toValue$1(values).filter((x) => toValue$1(list).findIndex((y) => compareFn(x, y)) === -1));\n return computed(() => symmetric ? [...toValue$1(diff1), ...toValue$1(diff2)] : toValue$1(diff1));\n } else {\n return diff1;\n }\n}\n\nfunction useArrayEvery(list, fn) {\n return computed(() => toValue$1(list).every((element, index, array) => fn(toValue$1(element), index, array)));\n}\n\nfunction useArrayFilter(list, fn) {\n return computed(() => toValue$1(list).map((i) => toValue$1(i)).filter(fn));\n}\n\nfunction useArrayFind(list, fn) {\n return computed(() => toValue$1(\n toValue$1(list).find((element, index, array) => fn(toValue$1(element), index, array))\n ));\n}\n\nfunction useArrayFindIndex(list, fn) {\n return computed(() => toValue$1(list).findIndex((element, index, array) => fn(toValue$1(element), index, array)));\n}\n\nfunction findLast(arr, cb) {\n let index = arr.length;\n while (index-- > 0) {\n if (cb(arr[index], index, arr))\n return arr[index];\n }\n return void 0;\n}\nfunction useArrayFindLast(list, fn) {\n return computed(() => toValue$1(\n !Array.prototype.findLast ? findLast(toValue$1(list), (element, index, array) => fn(toValue$1(element), index, array)) : toValue$1(list).findLast((element, index, array) => fn(toValue$1(element), index, array))\n ));\n}\n\nfunction isArrayIncludesOptions(obj) {\n return isObject(obj) && containsProp(obj, \"formIndex\", \"comparator\");\n}\nfunction useArrayIncludes(...args) {\n var _a;\n const list = args[0];\n const value = args[1];\n let comparator = args[2];\n let formIndex = 0;\n if (isArrayIncludesOptions(comparator)) {\n formIndex = (_a = comparator.fromIndex) != null ? _a : 0;\n comparator = comparator.comparator;\n }\n if (typeof comparator === \"string\") {\n const key = comparator;\n comparator = (element, value2) => element[key] === toValue$1(value2);\n }\n comparator = comparator != null ? comparator : (element, value2) => element === toValue$1(value2);\n return computed(() => toValue$1(list).slice(formIndex).some((element, index, array) => comparator(\n toValue$1(element),\n toValue$1(value),\n index,\n toValue$1(array)\n )));\n}\n\nfunction useArrayJoin(list, separator) {\n return computed(() => toValue$1(list).map((i) => toValue$1(i)).join(toValue$1(separator)));\n}\n\nfunction useArrayMap(list, fn) {\n return computed(() => toValue$1(list).map((i) => toValue$1(i)).map(fn));\n}\n\nfunction useArrayReduce(list, reducer, ...args) {\n const reduceCallback = (sum, value, index) => reducer(toValue$1(sum), toValue$1(value), index);\n return computed(() => {\n const resolved = toValue$1(list);\n return args.length ? resolved.reduce(reduceCallback, typeof args[0] === \"function\" ? toValue$1(args[0]()) : toValue$1(args[0])) : resolved.reduce(reduceCallback);\n });\n}\n\nfunction useArraySome(list, fn) {\n return computed(() => toValue$1(list).some((element, index, array) => fn(toValue$1(element), index, array)));\n}\n\nfunction uniq(array) {\n return Array.from(new Set(array));\n}\nfunction uniqueElementsBy(array, fn) {\n return array.reduce((acc, v) => {\n if (!acc.some((x) => fn(v, x, array)))\n acc.push(v);\n return acc;\n }, []);\n}\nfunction useArrayUnique(list, compareFn) {\n return computed(() => {\n const resolvedList = toValue$1(list).map((element) => toValue$1(element));\n return compareFn ? uniqueElementsBy(resolvedList, compareFn) : uniq(resolvedList);\n });\n}\n\nfunction useCounter(initialValue = 0, options = {}) {\n let _initialValue = unref(initialValue);\n const count = shallowRef(initialValue);\n const {\n max = Number.POSITIVE_INFINITY,\n min = Number.NEGATIVE_INFINITY\n } = options;\n const inc = (delta = 1) => count.value = Math.max(Math.min(max, count.value + delta), min);\n const dec = (delta = 1) => count.value = Math.min(Math.max(min, count.value - delta), max);\n const get = () => count.value;\n const set = (val) => count.value = Math.max(min, Math.min(max, val));\n const reset = (val = _initialValue) => {\n _initialValue = val;\n return set(val);\n };\n return { count, inc, dec, get, set, reset };\n}\n\nconst REGEX_PARSE = /^(\\d{4})[-/]?(\\d{1,2})?[-/]?(\\d{0,2})[T\\s]*(\\d{1,2})?:?(\\d{1,2})?:?(\\d{1,2})?[.:]?(\\d+)?$/i;\nconst REGEX_FORMAT = /[YMDHhms]o|\\[([^\\]]+)\\]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a{1,2}|A{1,2}|m{1,2}|s{1,2}|Z{1,2}|z{1,4}|SSS/g;\nfunction defaultMeridiem(hours, minutes, isLowercase, hasPeriod) {\n let m = hours < 12 ? \"AM\" : \"PM\";\n if (hasPeriod)\n m = m.split(\"\").reduce((acc, curr) => acc += `${curr}.`, \"\");\n return isLowercase ? m.toLowerCase() : m;\n}\nfunction formatOrdinal(num) {\n const suffixes = [\"th\", \"st\", \"nd\", \"rd\"];\n const v = num % 100;\n return num + (suffixes[(v - 20) % 10] || suffixes[v] || suffixes[0]);\n}\nfunction formatDate(date, formatStr, options = {}) {\n var _a;\n const years = date.getFullYear();\n const month = date.getMonth();\n const days = date.getDate();\n const hours = date.getHours();\n const minutes = date.getMinutes();\n const seconds = date.getSeconds();\n const milliseconds = date.getMilliseconds();\n const day = date.getDay();\n const meridiem = (_a = options.customMeridiem) != null ? _a : defaultMeridiem;\n const stripTimeZone = (dateString) => {\n var _a2;\n return (_a2 = dateString.split(\" \")[1]) != null ? _a2 : \"\";\n };\n const matches = {\n Yo: () => formatOrdinal(years),\n YY: () => String(years).slice(-2),\n YYYY: () => years,\n M: () => month + 1,\n Mo: () => formatOrdinal(month + 1),\n MM: () => `${month + 1}`.padStart(2, \"0\"),\n MMM: () => date.toLocaleDateString(toValue$1(options.locales), { month: \"short\" }),\n MMMM: () => date.toLocaleDateString(toValue$1(options.locales), { month: \"long\" }),\n D: () => String(days),\n Do: () => formatOrdinal(days),\n DD: () => `${days}`.padStart(2, \"0\"),\n H: () => String(hours),\n Ho: () => formatOrdinal(hours),\n HH: () => `${hours}`.padStart(2, \"0\"),\n h: () => `${hours % 12 || 12}`.padStart(1, \"0\"),\n ho: () => formatOrdinal(hours % 12 || 12),\n hh: () => `${hours % 12 || 12}`.padStart(2, \"0\"),\n m: () => String(minutes),\n mo: () => formatOrdinal(minutes),\n mm: () => `${minutes}`.padStart(2, \"0\"),\n s: () => String(seconds),\n so: () => formatOrdinal(seconds),\n ss: () => `${seconds}`.padStart(2, \"0\"),\n SSS: () => `${milliseconds}`.padStart(3, \"0\"),\n d: () => day,\n dd: () => date.toLocaleDateString(toValue$1(options.locales), { weekday: \"narrow\" }),\n ddd: () => date.toLocaleDateString(toValue$1(options.locales), { weekday: \"short\" }),\n dddd: () => date.toLocaleDateString(toValue$1(options.locales), { weekday: \"long\" }),\n A: () => meridiem(hours, minutes),\n AA: () => meridiem(hours, minutes, false, true),\n a: () => meridiem(hours, minutes, true),\n aa: () => meridiem(hours, minutes, true, true),\n z: () => stripTimeZone(date.toLocaleDateString(toValue$1(options.locales), { timeZoneName: \"shortOffset\" })),\n zz: () => stripTimeZone(date.toLocaleDateString(toValue$1(options.locales), { timeZoneName: \"shortOffset\" })),\n zzz: () => stripTimeZone(date.toLocaleDateString(toValue$1(options.locales), { timeZoneName: \"shortOffset\" })),\n zzzz: () => stripTimeZone(date.toLocaleDateString(toValue$1(options.locales), { timeZoneName: \"longOffset\" }))\n };\n return formatStr.replace(REGEX_FORMAT, (match, $1) => {\n var _a2, _b;\n return (_b = $1 != null ? $1 : (_a2 = matches[match]) == null ? void 0 : _a2.call(matches)) != null ? _b : match;\n });\n}\nfunction normalizeDate(date) {\n if (date === null)\n return new Date(Number.NaN);\n if (date === void 0)\n return /* @__PURE__ */ new Date();\n if (date instanceof Date)\n return new Date(date);\n if (typeof date === \"string\" && !/Z$/i.test(date)) {\n const d = date.match(REGEX_PARSE);\n if (d) {\n const m = d[2] - 1 || 0;\n const ms = (d[7] || \"0\").substring(0, 3);\n return new Date(d[1], m, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, ms);\n }\n }\n return new Date(date);\n}\nfunction useDateFormat(date, formatStr = \"HH:mm:ss\", options = {}) {\n return computed(() => formatDate(normalizeDate(toValue$1(date)), toValue$1(formatStr), options));\n}\n\nfunction useIntervalFn(cb, interval = 1e3, options = {}) {\n const {\n immediate = true,\n immediateCallback = false\n } = options;\n let timer = null;\n const isActive = shallowRef(false);\n function clean() {\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n }\n function pause() {\n isActive.value = false;\n clean();\n }\n function resume() {\n const intervalValue = toValue$1(interval);\n if (intervalValue <= 0)\n return;\n isActive.value = true;\n if (immediateCallback)\n cb();\n clean();\n if (isActive.value)\n timer = setInterval(cb, intervalValue);\n }\n if (immediate && isClient)\n resume();\n if (isRef(interval) || typeof interval === \"function\") {\n const stopWatch = watch(interval, () => {\n if (isActive.value && isClient)\n resume();\n });\n tryOnScopeDispose(stopWatch);\n }\n tryOnScopeDispose(pause);\n return {\n isActive,\n pause,\n resume\n };\n}\n\nfunction useInterval(interval = 1e3, options = {}) {\n const {\n controls: exposeControls = false,\n immediate = true,\n callback\n } = options;\n const counter = shallowRef(0);\n const update = () => counter.value += 1;\n const reset = () => {\n counter.value = 0;\n };\n const controls = useIntervalFn(\n callback ? () => {\n update();\n callback(counter.value);\n } : update,\n interval,\n { immediate }\n );\n if (exposeControls) {\n return {\n counter,\n reset,\n ...controls\n };\n } else {\n return counter;\n }\n}\n\nfunction useLastChanged(source, options = {}) {\n var _a;\n const ms = shallowRef((_a = options.initialValue) != null ? _a : null);\n watch(\n source,\n () => ms.value = timestamp(),\n options\n );\n return ms;\n}\n\nfunction useTimeoutFn(cb, interval, options = {}) {\n const {\n immediate = true,\n immediateCallback = false\n } = options;\n const isPending = shallowRef(false);\n let timer = null;\n function clear() {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n }\n function stop() {\n isPending.value = false;\n clear();\n }\n function start(...args) {\n if (immediateCallback)\n cb();\n clear();\n isPending.value = true;\n timer = setTimeout(() => {\n isPending.value = false;\n timer = null;\n cb(...args);\n }, toValue$1(interval));\n }\n if (immediate) {\n isPending.value = true;\n if (isClient)\n start();\n }\n tryOnScopeDispose(stop);\n return {\n isPending: readonly(isPending),\n start,\n stop\n };\n}\n\nfunction useTimeout(interval = 1e3, options = {}) {\n const {\n controls: exposeControls = false,\n callback\n } = options;\n const controls = useTimeoutFn(\n callback != null ? callback : noop,\n interval,\n options\n );\n const ready = computed(() => !controls.isPending.value);\n if (exposeControls) {\n return {\n ready,\n ...controls\n };\n } else {\n return ready;\n }\n}\n\nfunction useToNumber(value, options = {}) {\n const {\n method = \"parseFloat\",\n radix,\n nanToZero\n } = options;\n return computed(() => {\n let resolved = toValue$1(value);\n if (typeof method === \"function\")\n resolved = method(resolved);\n else if (typeof resolved === \"string\")\n resolved = Number[method](resolved, radix);\n if (nanToZero && Number.isNaN(resolved))\n resolved = 0;\n return resolved;\n });\n}\n\nfunction useToString(value) {\n return computed(() => `${toValue$1(value)}`);\n}\n\nfunction useToggle(initialValue = false, options = {}) {\n const {\n truthyValue = true,\n falsyValue = false\n } = options;\n const valueIsRef = isRef(initialValue);\n const _value = shallowRef(initialValue);\n function toggle(value) {\n if (arguments.length) {\n _value.value = value;\n return _value.value;\n } else {\n const truthy = toValue$1(truthyValue);\n _value.value = _value.value === truthy ? toValue$1(falsyValue) : truthy;\n return _value.value;\n }\n }\n if (valueIsRef)\n return toggle;\n else\n return [_value, toggle];\n}\n\nfunction watchArray(source, cb, options) {\n let oldList = (options == null ? void 0 : options.immediate) ? [] : [...typeof source === \"function\" ? source() : Array.isArray(source) ? source : toValue$1(source)];\n return watch(source, (newList, _, onCleanup) => {\n const oldListRemains = Array.from({ length: oldList.length });\n const added = [];\n for (const obj of newList) {\n let found = false;\n for (let i = 0; i < oldList.length; i++) {\n if (!oldListRemains[i] && obj === oldList[i]) {\n oldListRemains[i] = true;\n found = true;\n break;\n }\n }\n if (!found)\n added.push(obj);\n }\n const removed = oldList.filter((_2, i) => !oldListRemains[i]);\n cb(newList, oldList, added, removed, onCleanup);\n oldList = [...newList];\n }, options);\n}\n\nfunction watchAtMost(source, cb, options) {\n const {\n count,\n ...watchOptions\n } = options;\n const current = shallowRef(0);\n const stop = watchWithFilter(\n source,\n (...args) => {\n current.value += 1;\n if (current.value >= toValue$1(count))\n nextTick(() => stop());\n cb(...args);\n },\n watchOptions\n );\n return { count: current, stop };\n}\n\nfunction watchDebounced(source, cb, options = {}) {\n const {\n debounce = 0,\n maxWait = void 0,\n ...watchOptions\n } = options;\n return watchWithFilter(\n source,\n cb,\n {\n ...watchOptions,\n eventFilter: debounceFilter(debounce, { maxWait })\n }\n );\n}\n\nfunction watchDeep(source, cb, options) {\n return watch(\n source,\n cb,\n {\n ...options,\n deep: true\n }\n );\n}\n\nfunction watchIgnorable(source, cb, options = {}) {\n const {\n eventFilter = bypassFilter,\n ...watchOptions\n } = options;\n const filteredCb = createFilterWrapper(\n eventFilter,\n cb\n );\n let ignoreUpdates;\n let ignorePrevAsyncUpdates;\n let stop;\n if (watchOptions.flush === \"sync\") {\n const ignore = shallowRef(false);\n ignorePrevAsyncUpdates = () => {\n };\n ignoreUpdates = (updater) => {\n ignore.value = true;\n updater();\n ignore.value = false;\n };\n stop = watch(\n source,\n (...args) => {\n if (!ignore.value)\n filteredCb(...args);\n },\n watchOptions\n );\n } else {\n const disposables = [];\n const ignoreCounter = shallowRef(0);\n const syncCounter = shallowRef(0);\n ignorePrevAsyncUpdates = () => {\n ignoreCounter.value = syncCounter.value;\n };\n disposables.push(\n watch(\n source,\n () => {\n syncCounter.value++;\n },\n { ...watchOptions, flush: \"sync\" }\n )\n );\n ignoreUpdates = (updater) => {\n const syncCounterPrev = syncCounter.value;\n updater();\n ignoreCounter.value += syncCounter.value - syncCounterPrev;\n };\n disposables.push(\n watch(\n source,\n (...args) => {\n const ignore = ignoreCounter.value > 0 && ignoreCounter.value === syncCounter.value;\n ignoreCounter.value = 0;\n syncCounter.value = 0;\n if (ignore)\n return;\n filteredCb(...args);\n },\n watchOptions\n )\n );\n stop = () => {\n disposables.forEach((fn) => fn());\n };\n }\n return { stop, ignoreUpdates, ignorePrevAsyncUpdates };\n}\n\nfunction watchImmediate(source, cb, options) {\n return watch(\n source,\n cb,\n {\n ...options,\n immediate: true\n }\n );\n}\n\nfunction watchOnce(source, cb, options) {\n const stop = watch(source, (...args) => {\n nextTick(() => stop());\n return cb(...args);\n }, options);\n return stop;\n}\n\nfunction watchThrottled(source, cb, options = {}) {\n const {\n throttle = 0,\n trailing = true,\n leading = true,\n ...watchOptions\n } = options;\n return watchWithFilter(\n source,\n cb,\n {\n ...watchOptions,\n eventFilter: throttleFilter(throttle, trailing, leading)\n }\n );\n}\n\nfunction watchTriggerable(source, cb, options = {}) {\n let cleanupFn;\n function onEffect() {\n if (!cleanupFn)\n return;\n const fn = cleanupFn;\n cleanupFn = void 0;\n fn();\n }\n function onCleanup(callback) {\n cleanupFn = callback;\n }\n const _cb = (value, oldValue) => {\n onEffect();\n return cb(value, oldValue, onCleanup);\n };\n const res = watchIgnorable(source, _cb, options);\n const { ignoreUpdates } = res;\n const trigger = () => {\n let res2;\n ignoreUpdates(() => {\n res2 = _cb(getWatchSources(source), getOldValue(source));\n });\n return res2;\n };\n return {\n ...res,\n trigger\n };\n}\nfunction getWatchSources(sources) {\n if (isReactive(sources))\n return sources;\n if (Array.isArray(sources))\n return sources.map((item) => toValue$1(item));\n return toValue$1(sources);\n}\nfunction getOldValue(source) {\n return Array.isArray(source) ? source.map(() => void 0) : void 0;\n}\n\nfunction whenever(source, cb, options) {\n const stop = watch(\n source,\n (v, ov, onInvalidate) => {\n if (v) {\n if (options == null ? void 0 : options.once)\n nextTick(() => stop());\n cb(v, ov, onInvalidate);\n }\n },\n {\n ...options,\n once: false\n }\n );\n return stop;\n}\n\nexport { assert, refAutoReset as autoResetRef, bypassFilter, camelize, clamp, computedEager, computedWithControl, containsProp, computedWithControl as controlledComputed, controlledRef, createEventHook, createFilterWrapper, createGlobalState, createInjectionState, reactify as createReactiveFn, createRef, createSharedComposable, createSingletonPromise, debounceFilter, refDebounced as debouncedRef, watchDebounced as debouncedWatch, computedEager as eagerComputed, extendRef, formatDate, get, getLifeCycleTarget, hasOwn, hyphenate, identity, watchIgnorable as ignorableWatch, increaseWithUnit, injectLocal, invoke, isClient, isDef, isDefined, isIOS, isObject, isWorker, makeDestructurable, noop, normalizeDate, notNullish, now, objectEntries, objectOmit, objectPick, pausableFilter, watchPausable as pausableWatch, promiseTimeout, provideLocal, pxValue, rand, reactify, reactifyObject, reactiveComputed, reactiveOmit, reactivePick, refAutoReset, refDebounced, refDefault, refThrottled, refWithControl, resolveRef, resolveUnref, set, syncRef, syncRefs, throttleFilter, refThrottled as throttledRef, watchThrottled as throttledWatch, timestamp, toArray, toReactive, toRef, toRefs, toValue, tryOnBeforeMount, tryOnBeforeUnmount, tryOnMounted, tryOnScopeDispose, tryOnUnmounted, until, useArrayDifference, useArrayEvery, useArrayFilter, useArrayFind, useArrayFindIndex, useArrayFindLast, useArrayIncludes, useArrayJoin, useArrayMap, useArrayReduce, useArraySome, useArrayUnique, useCounter, useDateFormat, refDebounced as useDebounce, useDebounceFn, useInterval, useIntervalFn, useLastChanged, refThrottled as useThrottle, useThrottleFn, useTimeout, useTimeoutFn, useToNumber, useToString, useToggle, watchArray, watchAtMost, watchDebounced, watchDeep, watchIgnorable, watchImmediate, watchOnce, watchPausable, watchThrottled, watchTriggerable, watchWithFilter, whenever };\n", "import { noop, makeDestructurable, camelize, isClient, toArray, watchImmediate, isObject, tryOnScopeDispose, isIOS, notNullish, tryOnMounted, objectOmit, promiseTimeout, until, injectLocal, provideLocal, pxValue, increaseWithUnit, objectEntries, createRef, createSingletonPromise, useTimeoutFn, pausableWatch, toRef, createEventHook, useIntervalFn, computedWithControl, timestamp, pausableFilter, watchIgnorable, debounceFilter, bypassFilter, createFilterWrapper, toRefs, watchOnce, containsProp, hasOwn, throttleFilter, useDebounceFn, useThrottleFn, tryOnUnmounted, clamp, syncRef, objectPick, watchWithFilter, identity, isDef, whenever, isWorker } from '@vueuse/shared';\nexport * from '@vueuse/shared';\nimport { isRef, shallowRef, ref, watchEffect, computed, inject, defineComponent, h, TransitionGroup, shallowReactive, Fragment, toValue, unref, getCurrentInstance, onMounted, watch, customRef, onUpdated, readonly, reactive, hasInjectionContext, toRaw, nextTick, markRaw, getCurrentScope, isReadonly, onBeforeUpdate } from 'vue';\n\nfunction computedAsync(evaluationCallback, initialState, optionsOrRef) {\n let options;\n if (isRef(optionsOrRef)) {\n options = {\n evaluating: optionsOrRef\n };\n } else {\n options = optionsOrRef || {};\n }\n const {\n lazy = false,\n evaluating = void 0,\n shallow = true,\n onError = noop\n } = options;\n const started = shallowRef(!lazy);\n const current = shallow ? shallowRef(initialState) : ref(initialState);\n let counter = 0;\n watchEffect(async (onInvalidate) => {\n if (!started.value)\n return;\n counter++;\n const counterAtBeginning = counter;\n let hasFinished = false;\n if (evaluating) {\n Promise.resolve().then(() => {\n evaluating.value = true;\n });\n }\n try {\n const result = await evaluationCallback((cancelCallback) => {\n onInvalidate(() => {\n if (evaluating)\n evaluating.value = false;\n if (!hasFinished)\n cancelCallback();\n });\n });\n if (counterAtBeginning === counter)\n current.value = result;\n } catch (e) {\n onError(e);\n } finally {\n if (evaluating && counterAtBeginning === counter)\n evaluating.value = false;\n hasFinished = true;\n }\n });\n if (lazy) {\n return computed(() => {\n started.value = true;\n return current.value;\n });\n } else {\n return current;\n }\n}\n\nfunction computedInject(key, options, defaultSource, treatDefaultAsFactory) {\n let source = inject(key);\n if (defaultSource)\n source = inject(key, defaultSource);\n if (treatDefaultAsFactory)\n source = inject(key, defaultSource, treatDefaultAsFactory);\n if (typeof options === \"function\") {\n return computed((ctx) => options(source, ctx));\n } else {\n return computed({\n get: (ctx) => options.get(source, ctx),\n set: options.set\n });\n }\n}\n\nfunction createReusableTemplate(options = {}) {\n const {\n inheritAttrs = true\n } = options;\n const render = shallowRef();\n const define = /*@__PURE__*/ defineComponent({\n setup(_, { slots }) {\n return () => {\n render.value = slots.default;\n };\n }\n });\n const reuse = /*@__PURE__*/ defineComponent({\n inheritAttrs,\n props: options.props,\n setup(props, { attrs, slots }) {\n return () => {\n var _a;\n if (!render.value && process.env.NODE_ENV !== \"production\")\n throw new Error(\"[VueUse] Failed to find the definition of reusable template\");\n const vnode = (_a = render.value) == null ? void 0 : _a.call(render, {\n ...options.props == null ? keysToCamelKebabCase(attrs) : props,\n $slots: slots\n });\n return inheritAttrs && (vnode == null ? void 0 : vnode.length) === 1 ? vnode[0] : vnode;\n };\n }\n });\n return makeDestructurable(\n { define, reuse },\n [define, reuse]\n );\n}\nfunction keysToCamelKebabCase(obj) {\n const newObj = {};\n for (const key in obj)\n newObj[camelize(key)] = obj[key];\n return newObj;\n}\n\nfunction createTemplatePromise(options = {}) {\n let index = 0;\n const instances = ref([]);\n function create(...args) {\n const props = shallowReactive({\n key: index++,\n args,\n promise: void 0,\n resolve: () => {\n },\n reject: () => {\n },\n isResolving: false,\n options\n });\n instances.value.push(props);\n props.promise = new Promise((_resolve, _reject) => {\n props.resolve = (v) => {\n props.isResolving = true;\n return _resolve(v);\n };\n props.reject = _reject;\n }).finally(() => {\n props.promise = void 0;\n const index2 = instances.value.indexOf(props);\n if (index2 !== -1)\n instances.value.splice(index2, 1);\n });\n return props.promise;\n }\n function start(...args) {\n if (options.singleton && instances.value.length > 0)\n return instances.value[0].promise;\n return create(...args);\n }\n const component = /*@__PURE__*/ defineComponent((_, { slots }) => {\n const renderList = () => instances.value.map((props) => {\n var _a;\n return h(Fragment, { key: props.key }, (_a = slots.default) == null ? void 0 : _a.call(slots, props));\n });\n if (options.transition)\n return () => h(TransitionGroup, options.transition, renderList);\n return renderList;\n });\n component.start = start;\n return component;\n}\n\nfunction createUnrefFn(fn) {\n return function(...args) {\n return fn.apply(this, args.map((i) => toValue(i)));\n };\n}\n\nconst defaultWindow = isClient ? window : void 0;\nconst defaultDocument = isClient ? window.document : void 0;\nconst defaultNavigator = isClient ? window.navigator : void 0;\nconst defaultLocation = isClient ? window.location : void 0;\n\nfunction unrefElement(elRef) {\n var _a;\n const plain = toValue(elRef);\n return (_a = plain == null ? void 0 : plain.$el) != null ? _a : plain;\n}\n\nfunction useEventListener(...args) {\n const cleanups = [];\n const cleanup = () => {\n cleanups.forEach((fn) => fn());\n cleanups.length = 0;\n };\n const register = (el, event, listener, options) => {\n el.addEventListener(event, listener, options);\n return () => el.removeEventListener(event, listener, options);\n };\n const firstParamTargets = computed(() => {\n const test = toArray(toValue(args[0])).filter((e) => e != null);\n return test.every((e) => typeof e !== \"string\") ? test : void 0;\n });\n const stopWatch = watchImmediate(\n () => {\n var _a, _b;\n return [\n (_b = (_a = firstParamTargets.value) == null ? void 0 : _a.map((e) => unrefElement(e))) != null ? _b : [defaultWindow].filter((e) => e != null),\n toArray(toValue(firstParamTargets.value ? args[1] : args[0])),\n toArray(unref(firstParamTargets.value ? args[2] : args[1])),\n // @ts-expect-error - TypeScript gets the correct types, but somehow still complains\n toValue(firstParamTargets.value ? args[3] : args[2])\n ];\n },\n ([raw_targets, raw_events, raw_listeners, raw_options]) => {\n cleanup();\n if (!(raw_targets == null ? void 0 : raw_targets.length) || !(raw_events == null ? void 0 : raw_events.length) || !(raw_listeners == null ? void 0 : raw_listeners.length))\n return;\n const optionsClone = isObject(raw_options) ? { ...raw_options } : raw_options;\n cleanups.push(\n ...raw_targets.flatMap(\n (el) => raw_events.flatMap(\n (event) => raw_listeners.map((listener) => register(el, event, listener, optionsClone))\n )\n )\n );\n },\n { flush: \"post\" }\n );\n const stop = () => {\n stopWatch();\n cleanup();\n };\n tryOnScopeDispose(cleanup);\n return stop;\n}\n\nlet _iOSWorkaround = false;\nfunction onClickOutside(target, handler, options = {}) {\n const { window = defaultWindow, ignore = [], capture = true, detectIframe = false, controls = false } = options;\n if (!window) {\n return controls ? { stop: noop, cancel: noop, trigger: noop } : noop;\n }\n if (isIOS && !_iOSWorkaround) {\n _iOSWorkaround = true;\n const listenerOptions = { passive: true };\n Array.from(window.document.body.children).forEach((el) => useEventListener(el, \"click\", noop, listenerOptions));\n useEventListener(window.document.documentElement, \"click\", noop, listenerOptions);\n }\n let shouldListen = true;\n const shouldIgnore = (event) => {\n return toValue(ignore).some((target2) => {\n if (typeof target2 === \"string\") {\n return Array.from(window.document.querySelectorAll(target2)).some((el) => el === event.target || event.composedPath().includes(el));\n } else {\n const el = unrefElement(target2);\n return el && (event.target === el || event.composedPath().includes(el));\n }\n });\n };\n function hasMultipleRoots(target2) {\n const vm = toValue(target2);\n return vm && vm.$.subTree.shapeFlag === 16;\n }\n function checkMultipleRoots(target2, event) {\n const vm = toValue(target2);\n const children = vm.$.subTree && vm.$.subTree.children;\n if (children == null || !Array.isArray(children))\n return false;\n return children.some((child) => child.el === event.target || event.composedPath().includes(child.el));\n }\n const listener = (event) => {\n const el = unrefElement(target);\n if (event.target == null)\n return;\n if (!(el instanceof Element) && hasMultipleRoots(target) && checkMultipleRoots(target, event))\n return;\n if (!el || el === event.target || event.composedPath().includes(el))\n return;\n if (\"detail\" in event && event.detail === 0)\n shouldListen = !shouldIgnore(event);\n if (!shouldListen) {\n shouldListen = true;\n return;\n }\n handler(event);\n };\n let isProcessingClick = false;\n const cleanup = [\n useEventListener(window, \"click\", (event) => {\n if (!isProcessingClick) {\n isProcessingClick = true;\n setTimeout(() => {\n isProcessingClick = false;\n }, 0);\n listener(event);\n }\n }, { passive: true, capture }),\n useEventListener(window, \"pointerdown\", (e) => {\n const el = unrefElement(target);\n shouldListen = !shouldIgnore(e) && !!(el && !e.composedPath().includes(el));\n }, { passive: true }),\n detectIframe && useEventListener(window, \"blur\", (event) => {\n setTimeout(() => {\n var _a;\n const el = unrefElement(target);\n if (((_a = window.document.activeElement) == null ? void 0 : _a.tagName) === \"IFRAME\" && !(el == null ? void 0 : el.contains(window.document.activeElement))) {\n handler(event);\n }\n }, 0);\n }, { passive: true })\n ].filter(Boolean);\n const stop = () => cleanup.forEach((fn) => fn());\n if (controls) {\n return {\n stop,\n cancel: () => {\n shouldListen = false;\n },\n trigger: (event) => {\n shouldListen = true;\n listener(event);\n shouldListen = false;\n }\n };\n }\n return stop;\n}\n\nfunction useMounted() {\n const isMounted = shallowRef(false);\n const instance = getCurrentInstance();\n if (instance) {\n onMounted(() => {\n isMounted.value = true;\n }, instance);\n }\n return isMounted;\n}\n\nfunction useSupported(callback) {\n const isMounted = useMounted();\n return computed(() => {\n isMounted.value;\n return Boolean(callback());\n });\n}\n\nfunction useMutationObserver(target, callback, options = {}) {\n const { window = defaultWindow, ...mutationOptions } = options;\n let observer;\n const isSupported = useSupported(() => window && \"MutationObserver\" in window);\n const cleanup = () => {\n if (observer) {\n observer.disconnect();\n observer = void 0;\n }\n };\n const targets = computed(() => {\n const value = toValue(target);\n const items = toArray(value).map(unrefElement).filter(notNullish);\n return new Set(items);\n });\n const stopWatch = watch(\n () => targets.value,\n (targets2) => {\n cleanup();\n if (isSupported.value && targets2.size) {\n observer = new MutationObserver(callback);\n targets2.forEach((el) => observer.observe(el, mutationOptions));\n }\n },\n { immediate: true, flush: \"post\" }\n );\n const takeRecords = () => {\n return observer == null ? void 0 : observer.takeRecords();\n };\n const stop = () => {\n stopWatch();\n cleanup();\n };\n tryOnScopeDispose(stop);\n return {\n isSupported,\n stop,\n takeRecords\n };\n}\n\nfunction onElementRemoval(target, callback, options = {}) {\n const {\n window = defaultWindow,\n document = window == null ? void 0 : window.document,\n flush = \"sync\"\n } = options;\n if (!window || !document)\n return noop;\n let stopFn;\n const cleanupAndUpdate = (fn) => {\n stopFn == null ? void 0 : stopFn();\n stopFn = fn;\n };\n const stopWatch = watchEffect(() => {\n const el = unrefElement(target);\n if (el) {\n const { stop } = useMutationObserver(\n document,\n (mutationsList) => {\n const targetRemoved = mutationsList.map((mutation) => [...mutation.removedNodes]).flat().some((node) => node === el || node.contains(el));\n if (targetRemoved) {\n callback(mutationsList);\n }\n },\n {\n window,\n childList: true,\n subtree: true\n }\n );\n cleanupAndUpdate(stop);\n }\n }, { flush });\n const stopHandle = () => {\n stopWatch();\n cleanupAndUpdate();\n };\n tryOnScopeDispose(stopHandle);\n return stopHandle;\n}\n\nfunction createKeyPredicate(keyFilter) {\n if (typeof keyFilter === \"function\")\n return keyFilter;\n else if (typeof keyFilter === \"string\")\n return (event) => event.key === keyFilter;\n else if (Array.isArray(keyFilter))\n return (event) => keyFilter.includes(event.key);\n return () => true;\n}\nfunction onKeyStroke(...args) {\n let key;\n let handler;\n let options = {};\n if (args.length === 3) {\n key = args[0];\n handler = args[1];\n options = args[2];\n } else if (args.length === 2) {\n if (typeof args[1] === \"object\") {\n key = true;\n handler = args[0];\n options = args[1];\n } else {\n key = args[0];\n handler = args[1];\n }\n } else {\n key = true;\n handler = args[0];\n }\n const {\n target = defaultWindow,\n eventName = \"keydown\",\n passive = false,\n dedupe = false\n } = options;\n const predicate = createKeyPredicate(key);\n const listener = (e) => {\n if (e.repeat && toValue(dedupe))\n return;\n if (predicate(e))\n handler(e);\n };\n return useEventListener(target, eventName, listener, passive);\n}\nfunction onKeyDown(key, handler, options = {}) {\n return onKeyStroke(key, handler, { ...options, eventName: \"keydown\" });\n}\nfunction onKeyPressed(key, handler, options = {}) {\n return onKeyStroke(key, handler, { ...options, eventName: \"keypress\" });\n}\nfunction onKeyUp(key, handler, options = {}) {\n return onKeyStroke(key, handler, { ...options, eventName: \"keyup\" });\n}\n\nconst DEFAULT_DELAY = 500;\nconst DEFAULT_THRESHOLD = 10;\nfunction onLongPress(target, handler, options) {\n var _a, _b;\n const elementRef = computed(() => unrefElement(target));\n let timeout;\n let posStart;\n let startTimestamp;\n let hasLongPressed = false;\n function clear() {\n if (timeout) {\n clearTimeout(timeout);\n timeout = void 0;\n }\n posStart = void 0;\n startTimestamp = void 0;\n hasLongPressed = false;\n }\n function onRelease(ev) {\n var _a2, _b2, _c;\n const [_startTimestamp, _posStart, _hasLongPressed] = [startTimestamp, posStart, hasLongPressed];\n clear();\n if (!(options == null ? void 0 : options.onMouseUp) || !_posStart || !_startTimestamp)\n return;\n if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value)\n return;\n if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent)\n ev.preventDefault();\n if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)\n ev.stopPropagation();\n const dx = ev.x - _posStart.x;\n const dy = ev.y - _posStart.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n options.onMouseUp(ev.timeStamp - _startTimestamp, distance, _hasLongPressed);\n }\n function onDown(ev) {\n var _a2, _b2, _c, _d;\n if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value)\n return;\n clear();\n if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent)\n ev.preventDefault();\n if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)\n ev.stopPropagation();\n posStart = {\n x: ev.x,\n y: ev.y\n };\n startTimestamp = ev.timeStamp;\n timeout = setTimeout(\n () => {\n hasLongPressed = true;\n handler(ev);\n },\n (_d = options == null ? void 0 : options.delay) != null ? _d : DEFAULT_DELAY\n );\n }\n function onMove(ev) {\n var _a2, _b2, _c, _d;\n if (((_a2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _a2.self) && ev.target !== elementRef.value)\n return;\n if (!posStart || (options == null ? void 0 : options.distanceThreshold) === false)\n return;\n if ((_b2 = options == null ? void 0 : options.modifiers) == null ? void 0 : _b2.prevent)\n ev.preventDefault();\n if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)\n ev.stopPropagation();\n const dx = ev.x - posStart.x;\n const dy = ev.y - posStart.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n if (distance >= ((_d = options == null ? void 0 : options.distanceThreshold) != null ? _d : DEFAULT_THRESHOLD))\n clear();\n }\n const listenerOptions = {\n capture: (_a = options == null ? void 0 : options.modifiers) == null ? void 0 : _a.capture,\n once: (_b = options == null ? void 0 : options.modifiers) == null ? void 0 : _b.once\n };\n const cleanup = [\n useEventListener(elementRef, \"pointerdown\", onDown, listenerOptions),\n useEventListener(elementRef, \"pointermove\", onMove, listenerOptions),\n useEventListener(elementRef, [\"pointerup\", \"pointerleave\"], onRelease, listenerOptions)\n ];\n const stop = () => cleanup.forEach((fn) => fn());\n return stop;\n}\n\nfunction isFocusedElementEditable() {\n const { activeElement, body } = document;\n if (!activeElement)\n return false;\n if (activeElement === body)\n return false;\n switch (activeElement.tagName) {\n case \"INPUT\":\n case \"TEXTAREA\":\n return true;\n }\n return activeElement.hasAttribute(\"contenteditable\");\n}\nfunction isTypedCharValid({\n keyCode,\n metaKey,\n ctrlKey,\n altKey\n}) {\n if (metaKey || ctrlKey || altKey)\n return false;\n if (keyCode >= 48 && keyCode <= 57 || keyCode >= 96 && keyCode <= 105)\n return true;\n if (keyCode >= 65 && keyCode <= 90)\n return true;\n return false;\n}\nfunction onStartTyping(callback, options = {}) {\n const { document: document2 = defaultDocument } = options;\n const keydown = (event) => {\n if (!isFocusedElementEditable() && isTypedCharValid(event)) {\n callback(event);\n }\n };\n if (document2)\n useEventListener(document2, \"keydown\", keydown, { passive: true });\n}\n\nfunction templateRef(key, initialValue = null) {\n const instance = getCurrentInstance();\n let _trigger = () => {\n };\n const element = customRef((track, trigger) => {\n _trigger = trigger;\n return {\n get() {\n var _a, _b;\n track();\n return (_b = (_a = instance == null ? void 0 : instance.proxy) == null ? void 0 : _a.$refs[key]) != null ? _b : initialValue;\n },\n set() {\n }\n };\n });\n tryOnMounted(_trigger);\n onUpdated(_trigger);\n return element;\n}\n\nfunction useActiveElement(options = {}) {\n var _a;\n const {\n window = defaultWindow,\n deep = true,\n triggerOnRemoval = false\n } = options;\n const document = (_a = options.document) != null ? _a : window == null ? void 0 : window.document;\n const getDeepActiveElement = () => {\n var _a2;\n let element = document == null ? void 0 : document.activeElement;\n if (deep) {\n while (element == null ? void 0 : element.shadowRoot)\n element = (_a2 = element == null ? void 0 : element.shadowRoot) == null ? void 0 : _a2.activeElement;\n }\n return element;\n };\n const activeElement = shallowRef();\n const trigger = () => {\n activeElement.value = getDeepActiveElement();\n };\n if (window) {\n const listenerOptions = {\n capture: true,\n passive: true\n };\n useEventListener(\n window,\n \"blur\",\n (event) => {\n if (event.relatedTarget !== null)\n return;\n trigger();\n },\n listenerOptions\n );\n useEventListener(\n window,\n \"focus\",\n trigger,\n listenerOptions\n );\n }\n if (triggerOnRemoval) {\n onElementRemoval(activeElement, trigger, { document });\n }\n trigger();\n return activeElement;\n}\n\nfunction useRafFn(fn, options = {}) {\n const {\n immediate = true,\n fpsLimit = void 0,\n window = defaultWindow,\n once = false\n } = options;\n const isActive = shallowRef(false);\n const intervalLimit = computed(() => {\n return fpsLimit ? 1e3 / toValue(fpsLimit) : null;\n });\n let previousFrameTimestamp = 0;\n let rafId = null;\n function loop(timestamp) {\n if (!isActive.value || !window)\n return;\n if (!previousFrameTimestamp)\n previousFrameTimestamp = timestamp;\n const delta = timestamp - previousFrameTimestamp;\n if (intervalLimit.value && delta < intervalLimit.value) {\n rafId = window.requestAnimationFrame(loop);\n return;\n }\n previousFrameTimestamp = timestamp;\n fn({ delta, timestamp });\n if (once) {\n isActive.value = false;\n rafId = null;\n return;\n }\n rafId = window.requestAnimationFrame(loop);\n }\n function resume() {\n if (!isActive.value && window) {\n isActive.value = true;\n previousFrameTimestamp = 0;\n rafId = window.requestAnimationFrame(loop);\n }\n }\n function pause() {\n isActive.value = false;\n if (rafId != null && window) {\n window.cancelAnimationFrame(rafId);\n rafId = null;\n }\n }\n if (immediate)\n resume();\n tryOnScopeDispose(pause);\n return {\n isActive: readonly(isActive),\n pause,\n resume\n };\n}\n\nfunction useAnimate(target, keyframes, options) {\n let config;\n let animateOptions;\n if (isObject(options)) {\n config = options;\n animateOptions = objectOmit(options, [\"window\", \"immediate\", \"commitStyles\", \"persist\", \"onReady\", \"onError\"]);\n } else {\n config = { duration: options };\n animateOptions = options;\n }\n const {\n window = defaultWindow,\n immediate = true,\n commitStyles,\n persist,\n playbackRate: _playbackRate = 1,\n onReady,\n onError = (e) => {\n console.error(e);\n }\n } = config;\n const isSupported = useSupported(() => window && HTMLElement && \"animate\" in HTMLElement.prototype);\n const animate = shallowRef(void 0);\n const store = shallowReactive({\n startTime: null,\n currentTime: null,\n timeline: null,\n playbackRate: _playbackRate,\n pending: false,\n playState: immediate ? \"idle\" : \"paused\",\n replaceState: \"active\"\n });\n const pending = computed(() => store.pending);\n const playState = computed(() => store.playState);\n const replaceState = computed(() => store.replaceState);\n const startTime = computed({\n get() {\n return store.startTime;\n },\n set(value) {\n store.startTime = value;\n if (animate.value)\n animate.value.startTime = value;\n }\n });\n const currentTime = computed({\n get() {\n return store.currentTime;\n },\n set(value) {\n store.currentTime = value;\n if (animate.value) {\n animate.value.currentTime = value;\n syncResume();\n }\n }\n });\n const timeline = computed({\n get() {\n return store.timeline;\n },\n set(value) {\n store.timeline = value;\n if (animate.value)\n animate.value.timeline = value;\n }\n });\n const playbackRate = computed({\n get() {\n return store.playbackRate;\n },\n set(value) {\n store.playbackRate = value;\n if (animate.value)\n animate.value.playbackRate = value;\n }\n });\n const play = () => {\n if (animate.value) {\n try {\n animate.value.play();\n syncResume();\n } catch (e) {\n syncPause();\n onError(e);\n }\n } else {\n update();\n }\n };\n const pause = () => {\n var _a;\n try {\n (_a = animate.value) == null ? void 0 : _a.pause();\n syncPause();\n } catch (e) {\n onError(e);\n }\n };\n const reverse = () => {\n var _a;\n if (!animate.value)\n update();\n try {\n (_a = animate.value) == null ? void 0 : _a.reverse();\n syncResume();\n } catch (e) {\n syncPause();\n onError(e);\n }\n };\n const finish = () => {\n var _a;\n try {\n (_a = animate.value) == null ? void 0 : _a.finish();\n syncPause();\n } catch (e) {\n onError(e);\n }\n };\n const cancel = () => {\n var _a;\n try {\n (_a = animate.value) == null ? void 0 : _a.cancel();\n syncPause();\n } catch (e) {\n onError(e);\n }\n };\n watch(() => unrefElement(target), (el) => {\n if (el) {\n update();\n } else {\n animate.value = void 0;\n }\n });\n watch(() => keyframes, (value) => {\n if (animate.value) {\n update();\n const targetEl = unrefElement(target);\n if (targetEl) {\n animate.value.effect = new KeyframeEffect(\n targetEl,\n toValue(value),\n animateOptions\n );\n }\n }\n }, { deep: true });\n tryOnMounted(() => update(true), false);\n tryOnScopeDispose(cancel);\n function update(init) {\n const el = unrefElement(target);\n if (!isSupported.value || !el)\n return;\n if (!animate.value)\n animate.value = el.animate(toValue(keyframes), animateOptions);\n if (persist)\n animate.value.persist();\n if (_playbackRate !== 1)\n animate.value.playbackRate = _playbackRate;\n if (init && !immediate)\n animate.value.pause();\n else\n syncResume();\n onReady == null ? void 0 : onReady(animate.value);\n }\n const listenerOptions = { passive: true };\n useEventListener(animate, [\"cancel\", \"finish\", \"remove\"], syncPause, listenerOptions);\n useEventListener(animate, \"finish\", () => {\n var _a;\n if (commitStyles)\n (_a = animate.value) == null ? void 0 : _a.commitStyles();\n }, listenerOptions);\n const { resume: resumeRef, pause: pauseRef } = useRafFn(() => {\n if (!animate.value)\n return;\n store.pending = animate.value.pending;\n store.playState = animate.value.playState;\n store.replaceState = animate.value.replaceState;\n store.startTime = animate.value.startTime;\n store.currentTime = animate.value.currentTime;\n store.timeline = animate.value.timeline;\n store.playbackRate = animate.value.playbackRate;\n }, { immediate: false });\n function syncResume() {\n if (isSupported.value)\n resumeRef();\n }\n function syncPause() {\n if (isSupported.value && window)\n window.requestAnimationFrame(pauseRef);\n }\n return {\n isSupported,\n animate,\n // actions\n play,\n pause,\n reverse,\n finish,\n cancel,\n // state\n pending,\n playState,\n replaceState,\n startTime,\n currentTime,\n timeline,\n playbackRate\n };\n}\n\nfunction useAsyncQueue(tasks, options) {\n const {\n interrupt = true,\n onError = noop,\n onFinished = noop,\n signal\n } = options || {};\n const promiseState = {\n aborted: \"aborted\",\n fulfilled: \"fulfilled\",\n pending: \"pending\",\n rejected: \"rejected\"\n };\n const initialResult = Array.from(Array.from({ length: tasks.length }), () => ({ state: promiseState.pending, data: null }));\n const result = reactive(initialResult);\n const activeIndex = shallowRef(-1);\n if (!tasks || tasks.length === 0) {\n onFinished();\n return {\n activeIndex,\n result\n };\n }\n function updateResult(state, res) {\n activeIndex.value++;\n result[activeIndex.value].data = res;\n result[activeIndex.value].state = state;\n }\n tasks.reduce((prev, curr) => {\n return prev.then((prevRes) => {\n var _a;\n if (signal == null ? void 0 : signal.aborted) {\n updateResult(promiseState.aborted, new Error(\"aborted\"));\n return;\n }\n if (((_a = result[activeIndex.value]) == null ? void 0 : _a.state) === promiseState.rejected && interrupt) {\n onFinished();\n return;\n }\n const done = curr(prevRes).then((currentRes) => {\n updateResult(promiseState.fulfilled, currentRes);\n if (activeIndex.value === tasks.length - 1)\n onFinished();\n return currentRes;\n });\n if (!signal)\n return done;\n return Promise.race([done, whenAborted(signal)]);\n }).catch((e) => {\n if (signal == null ? void 0 : signal.aborted) {\n updateResult(promiseState.aborted, e);\n return e;\n }\n updateResult(promiseState.rejected, e);\n onError();\n return e;\n });\n }, Promise.resolve());\n return {\n activeIndex,\n result\n };\n}\nfunction whenAborted(signal) {\n return new Promise((resolve, reject) => {\n const error = new Error(\"aborted\");\n if (signal.aborted)\n reject(error);\n else\n signal.addEventListener(\"abort\", () => reject(error), { once: true });\n });\n}\n\nfunction useAsyncState(promise, initialState, options) {\n const {\n immediate = true,\n delay = 0,\n onError = noop,\n onSuccess = noop,\n resetOnExecute = true,\n shallow = true,\n throwError\n } = options != null ? options : {};\n const state = shallow ? shallowRef(initialState) : ref(initialState);\n const isReady = shallowRef(false);\n const isLoading = shallowRef(false);\n const error = shallowRef(void 0);\n async function execute(delay2 = 0, ...args) {\n if (resetOnExecute)\n state.value = initialState;\n error.value = void 0;\n isReady.value = false;\n isLoading.value = true;\n if (delay2 > 0)\n await promiseTimeout(delay2);\n const _promise = typeof promise === \"function\" ? promise(...args) : promise;\n try {\n const data = await _promise;\n state.value = data;\n isReady.value = true;\n onSuccess(data);\n } catch (e) {\n error.value = e;\n onError(e);\n if (throwError)\n throw e;\n } finally {\n isLoading.value = false;\n }\n return state.value;\n }\n if (immediate) {\n execute(delay);\n }\n const shell = {\n state,\n isReady,\n isLoading,\n error,\n execute\n };\n function waitUntilIsLoaded() {\n return new Promise((resolve, reject) => {\n until(isLoading).toBe(false).then(() => resolve(shell)).catch(reject);\n });\n }\n return {\n ...shell,\n then(onFulfilled, onRejected) {\n return waitUntilIsLoaded().then(onFulfilled, onRejected);\n }\n };\n}\n\nconst defaults = {\n array: (v) => JSON.stringify(v),\n object: (v) => JSON.stringify(v),\n set: (v) => JSON.stringify(Array.from(v)),\n map: (v) => JSON.stringify(Object.fromEntries(v)),\n null: () => \"\"\n};\nfunction getDefaultSerialization(target) {\n if (!target)\n return defaults.null;\n if (target instanceof Map)\n return defaults.map;\n else if (target instanceof Set)\n return defaults.set;\n else if (Array.isArray(target))\n return defaults.array;\n else\n return defaults.object;\n}\n\nfunction useBase64(target, options) {\n const base64 = shallowRef(\"\");\n const promise = shallowRef();\n function execute() {\n if (!isClient)\n return;\n promise.value = new Promise((resolve, reject) => {\n try {\n const _target = toValue(target);\n if (_target == null) {\n resolve(\"\");\n } else if (typeof _target === \"string\") {\n resolve(blobToBase64(new Blob([_target], { type: \"text/plain\" })));\n } else if (_target instanceof Blob) {\n resolve(blobToBase64(_target));\n } else if (_target instanceof ArrayBuffer) {\n resolve(window.btoa(String.fromCharCode(...new Uint8Array(_target))));\n } else if (_target instanceof HTMLCanvasElement) {\n resolve(_target.toDataURL(options == null ? void 0 : options.type, options == null ? void 0 : options.quality));\n } else if (_target instanceof HTMLImageElement) {\n const img = _target.cloneNode(false);\n img.crossOrigin = \"Anonymous\";\n imgLoaded(img).then(() => {\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n canvas.width = img.width;\n canvas.height = img.height;\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height);\n resolve(canvas.toDataURL(options == null ? void 0 : options.type, options == null ? void 0 : options.quality));\n }).catch(reject);\n } else if (typeof _target === \"object\") {\n const _serializeFn = (options == null ? void 0 : options.serializer) || getDefaultSerialization(_target);\n const serialized = _serializeFn(_target);\n return resolve(blobToBase64(new Blob([serialized], { type: \"application/json\" })));\n } else {\n reject(new Error(\"target is unsupported types\"));\n }\n } catch (error) {\n reject(error);\n }\n });\n promise.value.then((res) => {\n base64.value = (options == null ? void 0 : options.dataUrl) === false ? res.replace(/^data:.*?;base64,/, \"\") : res;\n });\n return promise.value;\n }\n if (isRef(target) || typeof target === \"function\")\n watch(target, execute, { immediate: true });\n else\n execute();\n return {\n base64,\n promise,\n execute\n };\n}\nfunction imgLoaded(img) {\n return new Promise((resolve, reject) => {\n if (!img.complete) {\n img.onload = () => {\n resolve();\n };\n img.onerror = reject;\n } else {\n resolve();\n }\n });\n}\nfunction blobToBase64(blob) {\n return new Promise((resolve, reject) => {\n const fr = new FileReader();\n fr.onload = (e) => {\n resolve(e.target.result);\n };\n fr.onerror = reject;\n fr.readAsDataURL(blob);\n });\n}\n\nfunction useBattery(options = {}) {\n const { navigator = defaultNavigator } = options;\n const events = [\"chargingchange\", \"chargingtimechange\", \"dischargingtimechange\", \"levelchange\"];\n const isSupported = useSupported(() => navigator && \"getBattery\" in navigator && typeof navigator.getBattery === \"function\");\n const charging = shallowRef(false);\n const chargingTime = shallowRef(0);\n const dischargingTime = shallowRef(0);\n const level = shallowRef(1);\n let battery;\n function updateBatteryInfo() {\n charging.value = this.charging;\n chargingTime.value = this.chargingTime || 0;\n dischargingTime.value = this.dischargingTime || 0;\n level.value = this.level;\n }\n if (isSupported.value) {\n navigator.getBattery().then((_battery) => {\n battery = _battery;\n updateBatteryInfo.call(battery);\n useEventListener(battery, events, updateBatteryInfo, { passive: true });\n });\n }\n return {\n isSupported,\n charging,\n chargingTime,\n dischargingTime,\n level\n };\n}\n\nfunction useBluetooth(options) {\n let {\n acceptAllDevices = false\n } = options || {};\n const {\n filters = void 0,\n optionalServices = void 0,\n navigator = defaultNavigator\n } = options || {};\n const isSupported = useSupported(() => navigator && \"bluetooth\" in navigator);\n const device = shallowRef();\n const error = shallowRef(null);\n watch(device, () => {\n connectToBluetoothGATTServer();\n });\n async function requestDevice() {\n if (!isSupported.value)\n return;\n error.value = null;\n if (filters && filters.length > 0)\n acceptAllDevices = false;\n try {\n device.value = await (navigator == null ? void 0 : navigator.bluetooth.requestDevice({\n acceptAllDevices,\n filters,\n optionalServices\n }));\n } catch (err) {\n error.value = err;\n }\n }\n const server = shallowRef();\n const isConnected = shallowRef(false);\n function reset() {\n isConnected.value = false;\n device.value = void 0;\n server.value = void 0;\n }\n async function connectToBluetoothGATTServer() {\n error.value = null;\n if (device.value && device.value.gatt) {\n useEventListener(device, \"gattserverdisconnected\", reset, { passive: true });\n try {\n server.value = await device.value.gatt.connect();\n isConnected.value = server.value.connected;\n } catch (err) {\n error.value = err;\n }\n }\n }\n tryOnMounted(() => {\n var _a;\n if (device.value)\n (_a = device.value.gatt) == null ? void 0 : _a.connect();\n });\n tryOnScopeDispose(() => {\n var _a;\n if (device.value)\n (_a = device.value.gatt) == null ? void 0 : _a.disconnect();\n });\n return {\n isSupported,\n isConnected: readonly(isConnected),\n // Device:\n device,\n requestDevice,\n // Server:\n server,\n // Errors:\n error\n };\n}\n\nconst ssrWidthSymbol = Symbol(\"vueuse-ssr-width\");\nfunction useSSRWidth() {\n const ssrWidth = hasInjectionContext() ? injectLocal(ssrWidthSymbol, null) : null;\n return typeof ssrWidth === \"number\" ? ssrWidth : void 0;\n}\nfunction provideSSRWidth(width, app) {\n if (app !== void 0) {\n app.provide(ssrWidthSymbol, width);\n } else {\n provideLocal(ssrWidthSymbol, width);\n }\n}\n\nfunction useMediaQuery(query, options = {}) {\n const { window = defaultWindow, ssrWidth = useSSRWidth() } = options;\n const isSupported = useSupported(() => window && \"matchMedia\" in window && typeof window.matchMedia === \"function\");\n const ssrSupport = shallowRef(typeof ssrWidth === \"number\");\n const mediaQuery = shallowRef();\n const matches = shallowRef(false);\n const handler = (event) => {\n matches.value = event.matches;\n };\n watchEffect(() => {\n if (ssrSupport.value) {\n ssrSupport.value = !isSupported.value;\n const queryStrings = toValue(query).split(\",\");\n matches.value = queryStrings.some((queryString) => {\n const not = queryString.includes(\"not all\");\n const minWidth = queryString.match(/\\(\\s*min-width:\\s*(-?\\d+(?:\\.\\d*)?[a-z]+\\s*)\\)/);\n const maxWidth = queryString.match(/\\(\\s*max-width:\\s*(-?\\d+(?:\\.\\d*)?[a-z]+\\s*)\\)/);\n let res = Boolean(minWidth || maxWidth);\n if (minWidth && res) {\n res = ssrWidth >= pxValue(minWidth[1]);\n }\n if (maxWidth && res) {\n res = ssrWidth <= pxValue(maxWidth[1]);\n }\n return not ? !res : res;\n });\n return;\n }\n if (!isSupported.value)\n return;\n mediaQuery.value = window.matchMedia(toValue(query));\n matches.value = mediaQuery.value.matches;\n });\n useEventListener(mediaQuery, \"change\", handler, { passive: true });\n return computed(() => matches.value);\n}\n\nconst breakpointsTailwind = {\n \"sm\": 640,\n \"md\": 768,\n \"lg\": 1024,\n \"xl\": 1280,\n \"2xl\": 1536\n};\nconst breakpointsBootstrapV5 = {\n xs: 0,\n sm: 576,\n md: 768,\n lg: 992,\n xl: 1200,\n xxl: 1400\n};\nconst breakpointsVuetifyV2 = {\n xs: 0,\n sm: 600,\n md: 960,\n lg: 1264,\n xl: 1904\n};\nconst breakpointsVuetifyV3 = {\n xs: 0,\n sm: 600,\n md: 960,\n lg: 1280,\n xl: 1920,\n xxl: 2560\n};\nconst breakpointsVuetify = breakpointsVuetifyV2;\nconst breakpointsAntDesign = {\n xs: 480,\n sm: 576,\n md: 768,\n lg: 992,\n xl: 1200,\n xxl: 1600\n};\nconst breakpointsQuasar = {\n xs: 0,\n sm: 600,\n md: 1024,\n lg: 1440,\n xl: 1920\n};\nconst breakpointsSematic = {\n mobileS: 320,\n mobileM: 375,\n mobileL: 425,\n tablet: 768,\n laptop: 1024,\n laptopL: 1440,\n desktop4K: 2560\n};\nconst breakpointsMasterCss = {\n \"3xs\": 360,\n \"2xs\": 480,\n \"xs\": 600,\n \"sm\": 768,\n \"md\": 1024,\n \"lg\": 1280,\n \"xl\": 1440,\n \"2xl\": 1600,\n \"3xl\": 1920,\n \"4xl\": 2560\n};\nconst breakpointsPrimeFlex = {\n sm: 576,\n md: 768,\n lg: 992,\n xl: 1200\n};\nconst breakpointsElement = {\n xs: 0,\n sm: 768,\n md: 992,\n lg: 1200,\n xl: 1920\n};\n\nfunction useBreakpoints(breakpoints, options = {}) {\n function getValue(k, delta) {\n let v = toValue(breakpoints[toValue(k)]);\n if (delta != null)\n v = increaseWithUnit(v, delta);\n if (typeof v === \"number\")\n v = `${v}px`;\n return v;\n }\n const { window = defaultWindow, strategy = \"min-width\", ssrWidth = useSSRWidth() } = options;\n const ssrSupport = typeof ssrWidth === \"number\";\n const mounted = ssrSupport ? shallowRef(false) : { value: true };\n if (ssrSupport) {\n tryOnMounted(() => mounted.value = !!window);\n }\n function match(query, size) {\n if (!mounted.value && ssrSupport) {\n return query === \"min\" ? ssrWidth >= pxValue(size) : ssrWidth <= pxValue(size);\n }\n if (!window)\n return false;\n return window.matchMedia(`(${query}-width: ${size})`).matches;\n }\n const greaterOrEqual = (k) => {\n return useMediaQuery(() => `(min-width: ${getValue(k)})`, options);\n };\n const smallerOrEqual = (k) => {\n return useMediaQuery(() => `(max-width: ${getValue(k)})`, options);\n };\n const shortcutMethods = Object.keys(breakpoints).reduce((shortcuts, k) => {\n Object.defineProperty(shortcuts, k, {\n get: () => strategy === \"min-width\" ? greaterOrEqual(k) : smallerOrEqual(k),\n enumerable: true,\n configurable: true\n });\n return shortcuts;\n }, {});\n function current() {\n const points = Object.keys(breakpoints).map((k) => [k, shortcutMethods[k], pxValue(getValue(k))]).sort((a, b) => a[2] - b[2]);\n return computed(() => points.filter(([, v]) => v.value).map(([k]) => k));\n }\n return Object.assign(shortcutMethods, {\n greaterOrEqual,\n smallerOrEqual,\n greater(k) {\n return useMediaQuery(() => `(min-width: ${getValue(k, 0.1)})`, options);\n },\n smaller(k) {\n return useMediaQuery(() => `(max-width: ${getValue(k, -0.1)})`, options);\n },\n between(a, b) {\n return useMediaQuery(() => `(min-width: ${getValue(a)}) and (max-width: ${getValue(b, -0.1)})`, options);\n },\n isGreater(k) {\n return match(\"min\", getValue(k, 0.1));\n },\n isGreaterOrEqual(k) {\n return match(\"min\", getValue(k));\n },\n isSmaller(k) {\n return match(\"max\", getValue(k, -0.1));\n },\n isSmallerOrEqual(k) {\n return match(\"max\", getValue(k));\n },\n isInBetween(a, b) {\n return match(\"min\", getValue(a)) && match(\"max\", getValue(b, -0.1));\n },\n current,\n active() {\n const bps = current();\n return computed(() => bps.value.length === 0 ? \"\" : bps.value.at(strategy === \"min-width\" ? -1 : 0));\n }\n });\n}\n\nfunction useBroadcastChannel(options) {\n const {\n name,\n window = defaultWindow\n } = options;\n const isSupported = useSupported(() => window && \"BroadcastChannel\" in window);\n const isClosed = shallowRef(false);\n const channel = ref();\n const data = ref();\n const error = shallowRef(null);\n const post = (data2) => {\n if (channel.value)\n channel.value.postMessage(data2);\n };\n const close = () => {\n if (channel.value)\n channel.value.close();\n isClosed.value = true;\n };\n if (isSupported.value) {\n tryOnMounted(() => {\n error.value = null;\n channel.value = new BroadcastChannel(name);\n const listenerOptions = {\n passive: true\n };\n useEventListener(channel, \"message\", (e) => {\n data.value = e.data;\n }, listenerOptions);\n useEventListener(channel, \"messageerror\", (e) => {\n error.value = e;\n }, listenerOptions);\n useEventListener(channel, \"close\", () => {\n isClosed.value = true;\n }, listenerOptions);\n });\n }\n tryOnScopeDispose(() => {\n close();\n });\n return {\n isSupported,\n channel,\n data,\n post,\n close,\n error,\n isClosed\n };\n}\n\nconst WRITABLE_PROPERTIES = [\n \"hash\",\n \"host\",\n \"hostname\",\n \"href\",\n \"pathname\",\n \"port\",\n \"protocol\",\n \"search\"\n];\nfunction useBrowserLocation(options = {}) {\n const { window = defaultWindow } = options;\n const refs = Object.fromEntries(\n WRITABLE_PROPERTIES.map((key) => [key, ref()])\n );\n for (const [key, ref] of objectEntries(refs)) {\n watch(ref, (value) => {\n if (!(window == null ? void 0 : window.location) || window.location[key] === value)\n return;\n window.location[key] = value;\n });\n }\n const buildState = (trigger) => {\n var _a;\n const { state: state2, length } = (window == null ? void 0 : window.history) || {};\n const { origin } = (window == null ? void 0 : window.location) || {};\n for (const key of WRITABLE_PROPERTIES)\n refs[key].value = (_a = window == null ? void 0 : window.location) == null ? void 0 : _a[key];\n return reactive({\n trigger,\n state: state2,\n length,\n origin,\n ...refs\n });\n };\n const state = ref(buildState(\"load\"));\n if (window) {\n const listenerOptions = { passive: true };\n useEventListener(window, \"popstate\", () => state.value = buildState(\"popstate\"), listenerOptions);\n useEventListener(window, \"hashchange\", () => state.value = buildState(\"hashchange\"), listenerOptions);\n }\n return state;\n}\n\nfunction useCached(refValue, comparator = (a, b) => a === b, options) {\n const { deepRefs = true, ...watchOptions } = options || {};\n const cachedValue = createRef(refValue.value, deepRefs);\n watch(() => refValue.value, (value) => {\n if (!comparator(value, cachedValue.value))\n cachedValue.value = value;\n }, watchOptions);\n return cachedValue;\n}\n\nfunction usePermission(permissionDesc, options = {}) {\n const {\n controls = false,\n navigator = defaultNavigator\n } = options;\n const isSupported = useSupported(() => navigator && \"permissions\" in navigator);\n const permissionStatus = shallowRef();\n const desc = typeof permissionDesc === \"string\" ? { name: permissionDesc } : permissionDesc;\n const state = shallowRef();\n const update = () => {\n var _a, _b;\n state.value = (_b = (_a = permissionStatus.value) == null ? void 0 : _a.state) != null ? _b : \"prompt\";\n };\n useEventListener(permissionStatus, \"change\", update, { passive: true });\n const query = createSingletonPromise(async () => {\n if (!isSupported.value)\n return;\n if (!permissionStatus.value) {\n try {\n permissionStatus.value = await navigator.permissions.query(desc);\n } catch (e) {\n permissionStatus.value = void 0;\n } finally {\n update();\n }\n }\n if (controls)\n return toRaw(permissionStatus.value);\n });\n query();\n if (controls) {\n return {\n state,\n isSupported,\n query\n };\n } else {\n return state;\n }\n}\n\nfunction useClipboard(options = {}) {\n const {\n navigator = defaultNavigator,\n read = false,\n source,\n copiedDuring = 1500,\n legacy = false\n } = options;\n const isClipboardApiSupported = useSupported(() => navigator && \"clipboard\" in navigator);\n const permissionRead = usePermission(\"clipboard-read\");\n const permissionWrite = usePermission(\"clipboard-write\");\n const isSupported = computed(() => isClipboardApiSupported.value || legacy);\n const text = shallowRef(\"\");\n const copied = shallowRef(false);\n const timeout = useTimeoutFn(() => copied.value = false, copiedDuring, { immediate: false });\n async function updateText() {\n let useLegacy = !(isClipboardApiSupported.value && isAllowed(permissionRead.value));\n if (!useLegacy) {\n try {\n text.value = await navigator.clipboard.readText();\n } catch (e) {\n useLegacy = true;\n }\n }\n if (useLegacy) {\n text.value = legacyRead();\n }\n }\n if (isSupported.value && read)\n useEventListener([\"copy\", \"cut\"], updateText, { passive: true });\n async function copy(value = toValue(source)) {\n if (isSupported.value && value != null) {\n let useLegacy = !(isClipboardApiSupported.value && isAllowed(permissionWrite.value));\n if (!useLegacy) {\n try {\n await navigator.clipboard.writeText(value);\n } catch (e) {\n useLegacy = true;\n }\n }\n if (useLegacy)\n legacyCopy(value);\n text.value = value;\n copied.value = true;\n timeout.start();\n }\n }\n function legacyCopy(value) {\n const ta = document.createElement(\"textarea\");\n ta.value = value != null ? value : \"\";\n ta.style.position = \"absolute\";\n ta.style.opacity = \"0\";\n document.body.appendChild(ta);\n ta.select();\n document.execCommand(\"copy\");\n ta.remove();\n }\n function legacyRead() {\n var _a, _b, _c;\n return (_c = (_b = (_a = document == null ? void 0 : document.getSelection) == null ? void 0 : _a.call(document)) == null ? void 0 : _b.toString()) != null ? _c : \"\";\n }\n function isAllowed(status) {\n return status === \"granted\" || status === \"prompt\";\n }\n return {\n isSupported,\n text,\n copied,\n copy\n };\n}\n\nfunction useClipboardItems(options = {}) {\n const {\n navigator = defaultNavigator,\n read = false,\n source,\n copiedDuring = 1500\n } = options;\n const isSupported = useSupported(() => navigator && \"clipboard\" in navigator);\n const content = ref([]);\n const copied = shallowRef(false);\n const timeout = useTimeoutFn(() => copied.value = false, copiedDuring, { immediate: false });\n function updateContent() {\n if (isSupported.value) {\n navigator.clipboard.read().then((items) => {\n content.value = items;\n });\n }\n }\n if (isSupported.value && read)\n useEventListener([\"copy\", \"cut\"], updateContent, { passive: true });\n async function copy(value = toValue(source)) {\n if (isSupported.value && value != null) {\n await navigator.clipboard.write(value);\n content.value = value;\n copied.value = true;\n timeout.start();\n }\n }\n return {\n isSupported,\n content,\n copied,\n copy\n };\n}\n\nfunction cloneFnJSON(source) {\n return JSON.parse(JSON.stringify(source));\n}\nfunction useCloned(source, options = {}) {\n const cloned = ref({});\n const isModified = shallowRef(false);\n let _lastSync = false;\n const {\n manual,\n clone = cloneFnJSON,\n // watch options\n deep = true,\n immediate = true\n } = options;\n watch(cloned, () => {\n if (_lastSync) {\n _lastSync = false;\n return;\n }\n isModified.value = true;\n }, {\n deep: true,\n flush: \"sync\"\n });\n function sync() {\n _lastSync = true;\n isModified.value = false;\n cloned.value = clone(toValue(source));\n }\n if (!manual && (isRef(source) || typeof source === \"function\")) {\n watch(source, sync, {\n ...options,\n deep,\n immediate\n });\n } else {\n sync();\n }\n return { cloned, isModified, sync };\n}\n\nconst _global = typeof globalThis !== \"undefined\" ? globalThis : typeof window !== \"undefined\" ? window : typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : {};\nconst globalKey = \"__vueuse_ssr_handlers__\";\nconst handlers = /* @__PURE__ */ getHandlers();\nfunction getHandlers() {\n if (!(globalKey in _global))\n _global[globalKey] = _global[globalKey] || {};\n return _global[globalKey];\n}\nfunction getSSRHandler(key, fallback) {\n return handlers[key] || fallback;\n}\nfunction setSSRHandler(key, fn) {\n handlers[key] = fn;\n}\n\nfunction usePreferredDark(options) {\n return useMediaQuery(\"(prefers-color-scheme: dark)\", options);\n}\n\nfunction guessSerializerType(rawInit) {\n return rawInit == null ? \"any\" : rawInit instanceof Set ? \"set\" : rawInit instanceof Map ? \"map\" : rawInit instanceof Date ? \"date\" : typeof rawInit === \"boolean\" ? \"boolean\" : typeof rawInit === \"string\" ? \"string\" : typeof rawInit === \"object\" ? \"object\" : !Number.isNaN(rawInit) ? \"number\" : \"any\";\n}\n\nconst StorageSerializers = {\n boolean: {\n read: (v) => v === \"true\",\n write: (v) => String(v)\n },\n object: {\n read: (v) => JSON.parse(v),\n write: (v) => JSON.stringify(v)\n },\n number: {\n read: (v) => Number.parseFloat(v),\n write: (v) => String(v)\n },\n any: {\n read: (v) => v,\n write: (v) => String(v)\n },\n string: {\n read: (v) => v,\n write: (v) => String(v)\n },\n map: {\n read: (v) => new Map(JSON.parse(v)),\n write: (v) => JSON.stringify(Array.from(v.entries()))\n },\n set: {\n read: (v) => new Set(JSON.parse(v)),\n write: (v) => JSON.stringify(Array.from(v))\n },\n date: {\n read: (v) => new Date(v),\n write: (v) => v.toISOString()\n }\n};\nconst customStorageEventName = \"vueuse-storage\";\nfunction useStorage(key, defaults, storage, options = {}) {\n var _a;\n const {\n flush = \"pre\",\n deep = true,\n listenToStorageChanges = true,\n writeDefaults = true,\n mergeDefaults = false,\n shallow,\n window = defaultWindow,\n eventFilter,\n onError = (e) => {\n console.error(e);\n },\n initOnMounted\n } = options;\n const data = (shallow ? shallowRef : ref)(typeof defaults === \"function\" ? defaults() : defaults);\n const keyComputed = computed(() => toValue(key));\n if (!storage) {\n try {\n storage = getSSRHandler(\"getDefaultStorage\", () => {\n var _a2;\n return (_a2 = defaultWindow) == null ? void 0 : _a2.localStorage;\n })();\n } catch (e) {\n onError(e);\n }\n }\n if (!storage)\n return data;\n const rawInit = toValue(defaults);\n const type = guessSerializerType(rawInit);\n const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type];\n const { pause: pauseWatch, resume: resumeWatch } = pausableWatch(\n data,\n () => write(data.value),\n { flush, deep, eventFilter }\n );\n watch(keyComputed, () => update(), { flush });\n if (window && listenToStorageChanges) {\n tryOnMounted(() => {\n if (storage instanceof Storage)\n useEventListener(window, \"storage\", update, { passive: true });\n else\n useEventListener(window, customStorageEventName, updateFromCustomEvent);\n if (initOnMounted)\n update();\n });\n }\n if (!initOnMounted)\n update();\n function dispatchWriteEvent(oldValue, newValue) {\n if (window) {\n const payload = {\n key: keyComputed.value,\n oldValue,\n newValue,\n storageArea: storage\n };\n window.dispatchEvent(storage instanceof Storage ? new StorageEvent(\"storage\", payload) : new CustomEvent(customStorageEventName, {\n detail: payload\n }));\n }\n }\n function write(v) {\n try {\n const oldValue = storage.getItem(keyComputed.value);\n if (v == null) {\n dispatchWriteEvent(oldValue, null);\n storage.removeItem(keyComputed.value);\n } else {\n const serialized = serializer.write(v);\n if (oldValue !== serialized) {\n storage.setItem(keyComputed.value, serialized);\n dispatchWriteEvent(oldValue, serialized);\n }\n }\n } catch (e) {\n onError(e);\n }\n }\n function read(event) {\n const rawValue = event ? event.newValue : storage.getItem(keyComputed.value);\n if (rawValue == null) {\n if (writeDefaults && rawInit != null)\n storage.setItem(keyComputed.value, serializer.write(rawInit));\n return rawInit;\n } else if (!event && mergeDefaults) {\n const value = serializer.read(rawValue);\n if (typeof mergeDefaults === \"function\")\n return mergeDefaults(value, rawInit);\n else if (type === \"object\" && !Array.isArray(value))\n return { ...rawInit, ...value };\n return value;\n } else if (typeof rawValue !== \"string\") {\n return rawValue;\n } else {\n return serializer.read(rawValue);\n }\n }\n function update(event) {\n if (event && event.storageArea !== storage)\n return;\n if (event && event.key == null) {\n data.value = rawInit;\n return;\n }\n if (event && event.key !== keyComputed.value)\n return;\n pauseWatch();\n try {\n if ((event == null ? void 0 : event.newValue) !== serializer.write(data.value))\n data.value = read(event);\n } catch (e) {\n onError(e);\n } finally {\n if (event)\n nextTick(resumeWatch);\n else\n resumeWatch();\n }\n }\n function updateFromCustomEvent(event) {\n update(event.detail);\n }\n return data;\n}\n\nconst CSS_DISABLE_TRANS = \"*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}\";\nfunction useColorMode(options = {}) {\n const {\n selector = \"html\",\n attribute = \"class\",\n initialValue = \"auto\",\n window = defaultWindow,\n storage,\n storageKey = \"vueuse-color-scheme\",\n listenToStorageChanges = true,\n storageRef,\n emitAuto,\n disableTransition = true\n } = options;\n const modes = {\n auto: \"\",\n light: \"light\",\n dark: \"dark\",\n ...options.modes || {}\n };\n const preferredDark = usePreferredDark({ window });\n const system = computed(() => preferredDark.value ? \"dark\" : \"light\");\n const store = storageRef || (storageKey == null ? toRef(initialValue) : useStorage(storageKey, initialValue, storage, { window, listenToStorageChanges }));\n const state = computed(() => store.value === \"auto\" ? system.value : store.value);\n const updateHTMLAttrs = getSSRHandler(\n \"updateHTMLAttrs\",\n (selector2, attribute2, value) => {\n const el = typeof selector2 === \"string\" ? window == null ? void 0 : window.document.querySelector(selector2) : unrefElement(selector2);\n if (!el)\n return;\n const classesToAdd = /* @__PURE__ */ new Set();\n const classesToRemove = /* @__PURE__ */ new Set();\n let attributeToChange = null;\n if (attribute2 === \"class\") {\n const current = value.split(/\\s/g);\n Object.values(modes).flatMap((i) => (i || \"\").split(/\\s/g)).filter(Boolean).forEach((v) => {\n if (current.includes(v))\n classesToAdd.add(v);\n else\n classesToRemove.add(v);\n });\n } else {\n attributeToChange = { key: attribute2, value };\n }\n if (classesToAdd.size === 0 && classesToRemove.size === 0 && attributeToChange === null)\n return;\n let style;\n if (disableTransition) {\n style = window.document.createElement(\"style\");\n style.appendChild(document.createTextNode(CSS_DISABLE_TRANS));\n window.document.head.appendChild(style);\n }\n for (const c of classesToAdd) {\n el.classList.add(c);\n }\n for (const c of classesToRemove) {\n el.classList.remove(c);\n }\n if (attributeToChange) {\n el.setAttribute(attributeToChange.key, attributeToChange.value);\n }\n if (disableTransition) {\n window.getComputedStyle(style).opacity;\n document.head.removeChild(style);\n }\n }\n );\n function defaultOnChanged(mode) {\n var _a;\n updateHTMLAttrs(selector, attribute, (_a = modes[mode]) != null ? _a : mode);\n }\n function onChanged(mode) {\n if (options.onChanged)\n options.onChanged(mode, defaultOnChanged);\n else\n defaultOnChanged(mode);\n }\n watch(state, onChanged, { flush: \"post\", immediate: true });\n tryOnMounted(() => onChanged(state.value));\n const auto = computed({\n get() {\n return emitAuto ? store.value : state.value;\n },\n set(v) {\n store.value = v;\n }\n });\n return Object.assign(auto, { store, system, state });\n}\n\nfunction useConfirmDialog(revealed = shallowRef(false)) {\n const confirmHook = createEventHook();\n const cancelHook = createEventHook();\n const revealHook = createEventHook();\n let _resolve = noop;\n const reveal = (data) => {\n revealHook.trigger(data);\n revealed.value = true;\n return new Promise((resolve) => {\n _resolve = resolve;\n });\n };\n const confirm = (data) => {\n revealed.value = false;\n confirmHook.trigger(data);\n _resolve({ data, isCanceled: false });\n };\n const cancel = (data) => {\n revealed.value = false;\n cancelHook.trigger(data);\n _resolve({ data, isCanceled: true });\n };\n return {\n isRevealed: computed(() => revealed.value),\n reveal,\n confirm,\n cancel,\n onReveal: revealHook.on,\n onConfirm: confirmHook.on,\n onCancel: cancelHook.on\n };\n}\n\nfunction useCountdown(initialCountdown, options) {\n var _a, _b;\n const remaining = shallowRef(toValue(initialCountdown));\n const intervalController = useIntervalFn(() => {\n var _a2, _b2;\n const value = remaining.value - 1;\n remaining.value = value < 0 ? 0 : value;\n (_a2 = options == null ? void 0 : options.onTick) == null ? void 0 : _a2.call(options);\n if (remaining.value <= 0) {\n intervalController.pause();\n (_b2 = options == null ? void 0 : options.onComplete) == null ? void 0 : _b2.call(options);\n }\n }, (_a = options == null ? void 0 : options.interval) != null ? _a : 1e3, { immediate: (_b = options == null ? void 0 : options.immediate) != null ? _b : false });\n const reset = (countdown) => {\n var _a2;\n remaining.value = (_a2 = toValue(countdown)) != null ? _a2 : toValue(initialCountdown);\n };\n const stop = () => {\n intervalController.pause();\n reset();\n };\n const resume = () => {\n if (!intervalController.isActive.value) {\n if (remaining.value > 0) {\n intervalController.resume();\n }\n }\n };\n const start = (countdown) => {\n reset(countdown);\n intervalController.resume();\n };\n return {\n remaining,\n reset,\n stop,\n start,\n pause: intervalController.pause,\n resume,\n isActive: intervalController.isActive\n };\n}\n\nfunction useCssVar(prop, target, options = {}) {\n const { window = defaultWindow, initialValue, observe = false } = options;\n const variable = shallowRef(initialValue);\n const elRef = computed(() => {\n var _a;\n return unrefElement(target) || ((_a = window == null ? void 0 : window.document) == null ? void 0 : _a.documentElement);\n });\n function updateCssVar() {\n var _a;\n const key = toValue(prop);\n const el = toValue(elRef);\n if (el && window && key) {\n const value = (_a = window.getComputedStyle(el).getPropertyValue(key)) == null ? void 0 : _a.trim();\n variable.value = value || variable.value || initialValue;\n }\n }\n if (observe) {\n useMutationObserver(elRef, updateCssVar, {\n attributeFilter: [\"style\", \"class\"],\n window\n });\n }\n watch(\n [elRef, () => toValue(prop)],\n (_, old) => {\n if (old[0] && old[1])\n old[0].style.removeProperty(old[1]);\n updateCssVar();\n },\n { immediate: true }\n );\n watch(\n [variable, elRef],\n ([val, el]) => {\n const raw_prop = toValue(prop);\n if ((el == null ? void 0 : el.style) && raw_prop) {\n if (val == null)\n el.style.removeProperty(raw_prop);\n else\n el.style.setProperty(raw_prop, val);\n }\n },\n { immediate: true }\n );\n return variable;\n}\n\nfunction useCurrentElement(rootComponent) {\n const vm = getCurrentInstance();\n const currentElement = computedWithControl(\n () => null,\n () => rootComponent ? unrefElement(rootComponent) : vm.proxy.$el\n );\n onUpdated(currentElement.trigger);\n onMounted(currentElement.trigger);\n return currentElement;\n}\n\nfunction useCycleList(list, options) {\n const state = shallowRef(getInitialValue());\n const listRef = toRef(list);\n const index = computed({\n get() {\n var _a;\n const targetList = listRef.value;\n let index2 = (options == null ? void 0 : options.getIndexOf) ? options.getIndexOf(state.value, targetList) : targetList.indexOf(state.value);\n if (index2 < 0)\n index2 = (_a = options == null ? void 0 : options.fallbackIndex) != null ? _a : 0;\n return index2;\n },\n set(v) {\n set(v);\n }\n });\n function set(i) {\n const targetList = listRef.value;\n const length = targetList.length;\n const index2 = (i % length + length) % length;\n const value = targetList[index2];\n state.value = value;\n return value;\n }\n function shift(delta = 1) {\n return set(index.value + delta);\n }\n function next(n = 1) {\n return shift(n);\n }\n function prev(n = 1) {\n return shift(-n);\n }\n function getInitialValue() {\n var _a, _b;\n return (_b = toValue((_a = options == null ? void 0 : options.initialValue) != null ? _a : toValue(list)[0])) != null ? _b : void 0;\n }\n watch(listRef, () => set(index.value));\n return {\n state,\n index,\n next,\n prev,\n go: set\n };\n}\n\nfunction useDark(options = {}) {\n const {\n valueDark = \"dark\",\n valueLight = \"\"\n } = options;\n const mode = useColorMode({\n ...options,\n onChanged: (mode2, defaultHandler) => {\n var _a;\n if (options.onChanged)\n (_a = options.onChanged) == null ? void 0 : _a.call(options, mode2 === \"dark\", defaultHandler, mode2);\n else\n defaultHandler(mode2);\n },\n modes: {\n dark: valueDark,\n light: valueLight\n }\n });\n const system = computed(() => mode.system.value);\n const isDark = computed({\n get() {\n return mode.value === \"dark\";\n },\n set(v) {\n const modeVal = v ? \"dark\" : \"light\";\n if (system.value === modeVal)\n mode.value = \"auto\";\n else\n mode.value = modeVal;\n }\n });\n return isDark;\n}\n\nfunction fnBypass(v) {\n return v;\n}\nfunction fnSetSource(source, value) {\n return source.value = value;\n}\nfunction defaultDump(clone) {\n return clone ? typeof clone === \"function\" ? clone : cloneFnJSON : fnBypass;\n}\nfunction defaultParse(clone) {\n return clone ? typeof clone === \"function\" ? clone : cloneFnJSON : fnBypass;\n}\nfunction useManualRefHistory(source, options = {}) {\n const {\n clone = false,\n dump = defaultDump(clone),\n parse = defaultParse(clone),\n setSource = fnSetSource\n } = options;\n function _createHistoryRecord() {\n return markRaw({\n snapshot: dump(source.value),\n timestamp: timestamp()\n });\n }\n const last = ref(_createHistoryRecord());\n const undoStack = ref([]);\n const redoStack = ref([]);\n const _setSource = (record) => {\n setSource(source, parse(record.snapshot));\n last.value = record;\n };\n const commit = () => {\n undoStack.value.unshift(last.value);\n last.value = _createHistoryRecord();\n if (options.capacity && undoStack.value.length > options.capacity)\n undoStack.value.splice(options.capacity, Number.POSITIVE_INFINITY);\n if (redoStack.value.length)\n redoStack.value.splice(0, redoStack.value.length);\n };\n const clear = () => {\n undoStack.value.splice(0, undoStack.value.length);\n redoStack.value.splice(0, redoStack.value.length);\n };\n const undo = () => {\n const state = undoStack.value.shift();\n if (state) {\n redoStack.value.unshift(last.value);\n _setSource(state);\n }\n };\n const redo = () => {\n const state = redoStack.value.shift();\n if (state) {\n undoStack.value.unshift(last.value);\n _setSource(state);\n }\n };\n const reset = () => {\n _setSource(last.value);\n };\n const history = computed(() => [last.value, ...undoStack.value]);\n const canUndo = computed(() => undoStack.value.length > 0);\n const canRedo = computed(() => redoStack.value.length > 0);\n return {\n source,\n undoStack,\n redoStack,\n last,\n history,\n canUndo,\n canRedo,\n clear,\n commit,\n reset,\n undo,\n redo\n };\n}\n\nfunction useRefHistory(source, options = {}) {\n const {\n deep = false,\n flush = \"pre\",\n eventFilter\n } = options;\n const {\n eventFilter: composedFilter,\n pause,\n resume: resumeTracking,\n isActive: isTracking\n } = pausableFilter(eventFilter);\n const {\n ignoreUpdates,\n ignorePrevAsyncUpdates,\n stop\n } = watchIgnorable(\n source,\n commit,\n { deep, flush, eventFilter: composedFilter }\n );\n function setSource(source2, value) {\n ignorePrevAsyncUpdates();\n ignoreUpdates(() => {\n source2.value = value;\n });\n }\n const manualHistory = useManualRefHistory(source, { ...options, clone: options.clone || deep, setSource });\n const { clear, commit: manualCommit } = manualHistory;\n function commit() {\n ignorePrevAsyncUpdates();\n manualCommit();\n }\n function resume(commitNow) {\n resumeTracking();\n if (commitNow)\n commit();\n }\n function batch(fn) {\n let canceled = false;\n const cancel = () => canceled = true;\n ignoreUpdates(() => {\n fn(cancel);\n });\n if (!canceled)\n commit();\n }\n function dispose() {\n stop();\n clear();\n }\n return {\n ...manualHistory,\n isTracking,\n pause,\n resume,\n commit,\n batch,\n dispose\n };\n}\n\nfunction useDebouncedRefHistory(source, options = {}) {\n const filter = options.debounce ? debounceFilter(options.debounce) : void 0;\n const history = useRefHistory(source, { ...options, eventFilter: filter });\n return {\n ...history\n };\n}\n\nfunction useDeviceMotion(options = {}) {\n const {\n window = defaultWindow,\n requestPermissions = false,\n eventFilter = bypassFilter\n } = options;\n const isSupported = useSupported(() => typeof DeviceMotionEvent !== \"undefined\");\n const requirePermissions = useSupported(() => isSupported.value && \"requestPermission\" in DeviceMotionEvent && typeof DeviceMotionEvent.requestPermission === \"function\");\n const permissionGranted = shallowRef(false);\n const acceleration = ref({ x: null, y: null, z: null });\n const rotationRate = ref({ alpha: null, beta: null, gamma: null });\n const interval = shallowRef(0);\n const accelerationIncludingGravity = ref({\n x: null,\n y: null,\n z: null\n });\n function init() {\n if (window) {\n const onDeviceMotion = createFilterWrapper(\n eventFilter,\n (event) => {\n var _a, _b, _c, _d, _e, _f, _g, _h, _i;\n acceleration.value = {\n x: ((_a = event.acceleration) == null ? void 0 : _a.x) || null,\n y: ((_b = event.acceleration) == null ? void 0 : _b.y) || null,\n z: ((_c = event.acceleration) == null ? void 0 : _c.z) || null\n };\n accelerationIncludingGravity.value = {\n x: ((_d = event.accelerationIncludingGravity) == null ? void 0 : _d.x) || null,\n y: ((_e = event.accelerationIncludingGravity) == null ? void 0 : _e.y) || null,\n z: ((_f = event.accelerationIncludingGravity) == null ? void 0 : _f.z) || null\n };\n rotationRate.value = {\n alpha: ((_g = event.rotationRate) == null ? void 0 : _g.alpha) || null,\n beta: ((_h = event.rotationRate) == null ? void 0 : _h.beta) || null,\n gamma: ((_i = event.rotationRate) == null ? void 0 : _i.gamma) || null\n };\n interval.value = event.interval;\n }\n );\n useEventListener(window, \"devicemotion\", onDeviceMotion, { passive: true });\n }\n }\n const ensurePermissions = async () => {\n if (!requirePermissions.value)\n permissionGranted.value = true;\n if (permissionGranted.value)\n return;\n if (requirePermissions.value) {\n const requestPermission = DeviceMotionEvent.requestPermission;\n try {\n const response = await requestPermission();\n if (response === \"granted\") {\n permissionGranted.value = true;\n init();\n }\n } catch (error) {\n console.error(error);\n }\n }\n };\n if (isSupported.value) {\n if (requestPermissions && requirePermissions.value) {\n ensurePermissions().then(() => init());\n } else {\n init();\n }\n }\n return {\n acceleration,\n accelerationIncludingGravity,\n rotationRate,\n interval,\n isSupported,\n requirePermissions,\n ensurePermissions,\n permissionGranted\n };\n}\n\nfunction useDeviceOrientation(options = {}) {\n const { window = defaultWindow } = options;\n const isSupported = useSupported(() => window && \"DeviceOrientationEvent\" in window);\n const isAbsolute = shallowRef(false);\n const alpha = shallowRef(null);\n const beta = shallowRef(null);\n const gamma = shallowRef(null);\n if (window && isSupported.value) {\n useEventListener(window, \"deviceorientation\", (event) => {\n isAbsolute.value = event.absolute;\n alpha.value = event.alpha;\n beta.value = event.beta;\n gamma.value = event.gamma;\n }, { passive: true });\n }\n return {\n isSupported,\n isAbsolute,\n alpha,\n beta,\n gamma\n };\n}\n\nfunction useDevicePixelRatio(options = {}) {\n const {\n window = defaultWindow\n } = options;\n const pixelRatio = shallowRef(1);\n const query = useMediaQuery(() => `(resolution: ${pixelRatio.value}dppx)`, options);\n let stop = noop;\n if (window) {\n stop = watchImmediate(query, () => pixelRatio.value = window.devicePixelRatio);\n }\n return {\n pixelRatio: readonly(pixelRatio),\n stop\n };\n}\n\nfunction useDevicesList(options = {}) {\n const {\n navigator = defaultNavigator,\n requestPermissions = false,\n constraints = { audio: true, video: true },\n onUpdated\n } = options;\n const devices = ref([]);\n const videoInputs = computed(() => devices.value.filter((i) => i.kind === \"videoinput\"));\n const audioInputs = computed(() => devices.value.filter((i) => i.kind === \"audioinput\"));\n const audioOutputs = computed(() => devices.value.filter((i) => i.kind === \"audiooutput\"));\n const isSupported = useSupported(() => navigator && navigator.mediaDevices && navigator.mediaDevices.enumerateDevices);\n const permissionGranted = shallowRef(false);\n let stream;\n async function update() {\n if (!isSupported.value)\n return;\n devices.value = await navigator.mediaDevices.enumerateDevices();\n onUpdated == null ? void 0 : onUpdated(devices.value);\n if (stream) {\n stream.getTracks().forEach((t) => t.stop());\n stream = null;\n }\n }\n async function ensurePermissions() {\n const deviceName = constraints.video ? \"camera\" : \"microphone\";\n if (!isSupported.value)\n return false;\n if (permissionGranted.value)\n return true;\n const { state, query } = usePermission(deviceName, { controls: true });\n await query();\n if (state.value !== \"granted\") {\n let granted = true;\n try {\n stream = await navigator.mediaDevices.getUserMedia(constraints);\n } catch (e) {\n stream = null;\n granted = false;\n }\n update();\n permissionGranted.value = granted;\n } else {\n permissionGranted.value = true;\n }\n return permissionGranted.value;\n }\n if (isSupported.value) {\n if (requestPermissions)\n ensurePermissions();\n useEventListener(navigator.mediaDevices, \"devicechange\", update, { passive: true });\n update();\n }\n return {\n devices,\n ensurePermissions,\n permissionGranted,\n videoInputs,\n audioInputs,\n audioOutputs,\n isSupported\n };\n}\n\nfunction useDisplayMedia(options = {}) {\n var _a;\n const enabled = shallowRef((_a = options.enabled) != null ? _a : false);\n const video = options.video;\n const audio = options.audio;\n const { navigator = defaultNavigator } = options;\n const isSupported = useSupported(() => {\n var _a2;\n return (_a2 = navigator == null ? void 0 : navigator.mediaDevices) == null ? void 0 : _a2.getDisplayMedia;\n });\n const constraint = { audio, video };\n const stream = shallowRef();\n async function _start() {\n var _a2;\n if (!isSupported.value || stream.value)\n return;\n stream.value = await navigator.mediaDevices.getDisplayMedia(constraint);\n (_a2 = stream.value) == null ? void 0 : _a2.getTracks().forEach((t) => useEventListener(t, \"ended\", stop, { passive: true }));\n return stream.value;\n }\n async function _stop() {\n var _a2;\n (_a2 = stream.value) == null ? void 0 : _a2.getTracks().forEach((t) => t.stop());\n stream.value = void 0;\n }\n function stop() {\n _stop();\n enabled.value = false;\n }\n async function start() {\n await _start();\n if (stream.value)\n enabled.value = true;\n return stream.value;\n }\n watch(\n enabled,\n (v) => {\n if (v)\n _start();\n else\n _stop();\n },\n { immediate: true }\n );\n return {\n isSupported,\n stream,\n start,\n stop,\n enabled\n };\n}\n\nfunction useDocumentVisibility(options = {}) {\n const { document = defaultDocument } = options;\n if (!document)\n return shallowRef(\"visible\");\n const visibility = shallowRef(document.visibilityState);\n useEventListener(document, \"visibilitychange\", () => {\n visibility.value = document.visibilityState;\n }, { passive: true });\n return visibility;\n}\n\nfunction useDraggable(target, options = {}) {\n var _a;\n const {\n pointerTypes,\n preventDefault,\n stopPropagation,\n exact,\n onMove,\n onEnd,\n onStart,\n initialValue,\n axis = \"both\",\n draggingElement = defaultWindow,\n containerElement,\n handle: draggingHandle = target,\n buttons = [0]\n } = options;\n const position = ref(\n (_a = toValue(initialValue)) != null ? _a : { x: 0, y: 0 }\n );\n const pressedDelta = ref();\n const filterEvent = (e) => {\n if (pointerTypes)\n return pointerTypes.includes(e.pointerType);\n return true;\n };\n const handleEvent = (e) => {\n if (toValue(preventDefault))\n e.preventDefault();\n if (toValue(stopPropagation))\n e.stopPropagation();\n };\n const start = (e) => {\n var _a2;\n if (!toValue(buttons).includes(e.button))\n return;\n if (toValue(options.disabled) || !filterEvent(e))\n return;\n if (toValue(exact) && e.target !== toValue(target))\n return;\n const container = toValue(containerElement);\n const containerRect = (_a2 = container == null ? void 0 : container.getBoundingClientRect) == null ? void 0 : _a2.call(container);\n const targetRect = toValue(target).getBoundingClientRect();\n const pos = {\n x: e.clientX - (container ? targetRect.left - containerRect.left + container.scrollLeft : targetRect.left),\n y: e.clientY - (container ? targetRect.top - containerRect.top + container.scrollTop : targetRect.top)\n };\n if ((onStart == null ? void 0 : onStart(pos, e)) === false)\n return;\n pressedDelta.value = pos;\n handleEvent(e);\n };\n const move = (e) => {\n if (toValue(options.disabled) || !filterEvent(e))\n return;\n if (!pressedDelta.value)\n return;\n const container = toValue(containerElement);\n const targetRect = toValue(target).getBoundingClientRect();\n let { x, y } = position.value;\n if (axis === \"x\" || axis === \"both\") {\n x = e.clientX - pressedDelta.value.x;\n if (container)\n x = Math.min(Math.max(0, x), container.scrollWidth - targetRect.width);\n }\n if (axis === \"y\" || axis === \"both\") {\n y = e.clientY - pressedDelta.value.y;\n if (container)\n y = Math.min(Math.max(0, y), container.scrollHeight - targetRect.height);\n }\n position.value = {\n x,\n y\n };\n onMove == null ? void 0 : onMove(position.value, e);\n handleEvent(e);\n };\n const end = (e) => {\n if (toValue(options.disabled) || !filterEvent(e))\n return;\n if (!pressedDelta.value)\n return;\n pressedDelta.value = void 0;\n onEnd == null ? void 0 : onEnd(position.value, e);\n handleEvent(e);\n };\n if (isClient) {\n const config = () => {\n var _a2;\n return {\n capture: (_a2 = options.capture) != null ? _a2 : true,\n passive: !toValue(preventDefault)\n };\n };\n useEventListener(draggingHandle, \"pointerdown\", start, config);\n useEventListener(draggingElement, \"pointermove\", move, config);\n useEventListener(draggingElement, \"pointerup\", end, config);\n }\n return {\n ...toRefs(position),\n position,\n isDragging: computed(() => !!pressedDelta.value),\n style: computed(\n () => `left:${position.value.x}px;top:${position.value.y}px;`\n )\n };\n}\n\nfunction useDropZone(target, options = {}) {\n var _a, _b;\n const isOverDropZone = shallowRef(false);\n const files = shallowRef(null);\n let counter = 0;\n let isValid = true;\n if (isClient) {\n const _options = typeof options === \"function\" ? { onDrop: options } : options;\n const multiple = (_a = _options.multiple) != null ? _a : true;\n const preventDefaultForUnhandled = (_b = _options.preventDefaultForUnhandled) != null ? _b : false;\n const getFiles = (event) => {\n var _a2, _b2;\n const list = Array.from((_b2 = (_a2 = event.dataTransfer) == null ? void 0 : _a2.files) != null ? _b2 : []);\n return list.length === 0 ? null : multiple ? list : [list[0]];\n };\n const checkDataTypes = (types) => {\n const dataTypes = unref(_options.dataTypes);\n if (typeof dataTypes === \"function\")\n return dataTypes(types);\n if (!(dataTypes == null ? void 0 : dataTypes.length))\n return true;\n if (types.length === 0)\n return false;\n return types.every(\n (type) => dataTypes.some((allowedType) => type.includes(allowedType))\n );\n };\n const checkValidity = (items) => {\n const types = Array.from(items != null ? items : []).map((item) => item.type);\n const dataTypesValid = checkDataTypes(types);\n const multipleFilesValid = multiple || items.length <= 1;\n return dataTypesValid && multipleFilesValid;\n };\n const isSafari = () => /^(?:(?!chrome|android).)*safari/i.test(navigator.userAgent) && !(\"chrome\" in window);\n const handleDragEvent = (event, eventType) => {\n var _a2, _b2, _c, _d, _e, _f;\n const dataTransferItemList = (_a2 = event.dataTransfer) == null ? void 0 : _a2.items;\n isValid = (_b2 = dataTransferItemList && checkValidity(dataTransferItemList)) != null ? _b2 : false;\n if (preventDefaultForUnhandled) {\n event.preventDefault();\n }\n if (!isSafari() && !isValid) {\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = \"none\";\n }\n return;\n }\n event.preventDefault();\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = \"copy\";\n }\n const currentFiles = getFiles(event);\n switch (eventType) {\n case \"enter\":\n counter += 1;\n isOverDropZone.value = true;\n (_c = _options.onEnter) == null ? void 0 : _c.call(_options, null, event);\n break;\n case \"over\":\n (_d = _options.onOver) == null ? void 0 : _d.call(_options, null, event);\n break;\n case \"leave\":\n counter -= 1;\n if (counter === 0)\n isOverDropZone.value = false;\n (_e = _options.onLeave) == null ? void 0 : _e.call(_options, null, event);\n break;\n case \"drop\":\n counter = 0;\n isOverDropZone.value = false;\n if (isValid) {\n files.value = currentFiles;\n (_f = _options.onDrop) == null ? void 0 : _f.call(_options, currentFiles, event);\n }\n break;\n }\n };\n useEventListener(target, \"dragenter\", (event) => handleDragEvent(event, \"enter\"));\n useEventListener(target, \"dragover\", (event) => handleDragEvent(event, \"over\"));\n useEventListener(target, \"dragleave\", (event) => handleDragEvent(event, \"leave\"));\n useEventListener(target, \"drop\", (event) => handleDragEvent(event, \"drop\"));\n }\n return {\n files,\n isOverDropZone\n };\n}\n\nfunction useResizeObserver(target, callback, options = {}) {\n const { window = defaultWindow, ...observerOptions } = options;\n let observer;\n const isSupported = useSupported(() => window && \"ResizeObserver\" in window);\n const cleanup = () => {\n if (observer) {\n observer.disconnect();\n observer = void 0;\n }\n };\n const targets = computed(() => {\n const _targets = toValue(target);\n return Array.isArray(_targets) ? _targets.map((el) => unrefElement(el)) : [unrefElement(_targets)];\n });\n const stopWatch = watch(\n targets,\n (els) => {\n cleanup();\n if (isSupported.value && window) {\n observer = new ResizeObserver(callback);\n for (const _el of els) {\n if (_el)\n observer.observe(_el, observerOptions);\n }\n }\n },\n { immediate: true, flush: \"post\" }\n );\n const stop = () => {\n cleanup();\n stopWatch();\n };\n tryOnScopeDispose(stop);\n return {\n isSupported,\n stop\n };\n}\n\nfunction useElementBounding(target, options = {}) {\n const {\n reset = true,\n windowResize = true,\n windowScroll = true,\n immediate = true,\n updateTiming = \"sync\"\n } = options;\n const height = shallowRef(0);\n const bottom = shallowRef(0);\n const left = shallowRef(0);\n const right = shallowRef(0);\n const top = shallowRef(0);\n const width = shallowRef(0);\n const x = shallowRef(0);\n const y = shallowRef(0);\n function recalculate() {\n const el = unrefElement(target);\n if (!el) {\n if (reset) {\n height.value = 0;\n bottom.value = 0;\n left.value = 0;\n right.value = 0;\n top.value = 0;\n width.value = 0;\n x.value = 0;\n y.value = 0;\n }\n return;\n }\n const rect = el.getBoundingClientRect();\n height.value = rect.height;\n bottom.value = rect.bottom;\n left.value = rect.left;\n right.value = rect.right;\n top.value = rect.top;\n width.value = rect.width;\n x.value = rect.x;\n y.value = rect.y;\n }\n function update() {\n if (updateTiming === \"sync\")\n recalculate();\n else if (updateTiming === \"next-frame\")\n requestAnimationFrame(() => recalculate());\n }\n useResizeObserver(target, update);\n watch(() => unrefElement(target), (ele) => !ele && update());\n useMutationObserver(target, update, {\n attributeFilter: [\"style\", \"class\"]\n });\n if (windowScroll)\n useEventListener(\"scroll\", update, { capture: true, passive: true });\n if (windowResize)\n useEventListener(\"resize\", update, { passive: true });\n tryOnMounted(() => {\n if (immediate)\n update();\n });\n return {\n height,\n bottom,\n left,\n right,\n top,\n width,\n x,\n y,\n update\n };\n}\n\nfunction useElementByPoint(options) {\n const {\n x,\n y,\n document = defaultDocument,\n multiple,\n interval = \"requestAnimationFrame\",\n immediate = true\n } = options;\n const isSupported = useSupported(() => {\n if (toValue(multiple))\n return document && \"elementsFromPoint\" in document;\n return document && \"elementFromPoint\" in document;\n });\n const element = shallowRef(null);\n const cb = () => {\n var _a, _b;\n element.value = toValue(multiple) ? (_a = document == null ? void 0 : document.elementsFromPoint(toValue(x), toValue(y))) != null ? _a : [] : (_b = document == null ? void 0 : document.elementFromPoint(toValue(x), toValue(y))) != null ? _b : null;\n };\n const controls = interval === \"requestAnimationFrame\" ? useRafFn(cb, { immediate }) : useIntervalFn(cb, interval, { immediate });\n return {\n isSupported,\n element,\n ...controls\n };\n}\n\nfunction useElementHover(el, options = {}) {\n const {\n delayEnter = 0,\n delayLeave = 0,\n triggerOnRemoval = false,\n window = defaultWindow\n } = options;\n const isHovered = shallowRef(false);\n let timer;\n const toggle = (entering) => {\n const delay = entering ? delayEnter : delayLeave;\n if (timer) {\n clearTimeout(timer);\n timer = void 0;\n }\n if (delay)\n timer = setTimeout(() => isHovered.value = entering, delay);\n else\n isHovered.value = entering;\n };\n if (!window)\n return isHovered;\n useEventListener(el, \"mouseenter\", () => toggle(true), { passive: true });\n useEventListener(el, \"mouseleave\", () => toggle(false), { passive: true });\n if (triggerOnRemoval) {\n onElementRemoval(\n computed(() => unrefElement(el)),\n () => toggle(false)\n );\n }\n return isHovered;\n}\n\nfunction useElementSize(target, initialSize = { width: 0, height: 0 }, options = {}) {\n const { window = defaultWindow, box = \"content-box\" } = options;\n const isSVG = computed(() => {\n var _a, _b;\n return (_b = (_a = unrefElement(target)) == null ? void 0 : _a.namespaceURI) == null ? void 0 : _b.includes(\"svg\");\n });\n const width = shallowRef(initialSize.width);\n const height = shallowRef(initialSize.height);\n const { stop: stop1 } = useResizeObserver(\n target,\n ([entry]) => {\n const boxSize = box === \"border-box\" ? entry.borderBoxSize : box === \"content-box\" ? entry.contentBoxSize : entry.devicePixelContentBoxSize;\n if (window && isSVG.value) {\n const $elem = unrefElement(target);\n if ($elem) {\n const rect = $elem.getBoundingClientRect();\n width.value = rect.width;\n height.value = rect.height;\n }\n } else {\n if (boxSize) {\n const formatBoxSize = toArray(boxSize);\n width.value = formatBoxSize.reduce((acc, { inlineSize }) => acc + inlineSize, 0);\n height.value = formatBoxSize.reduce((acc, { blockSize }) => acc + blockSize, 0);\n } else {\n width.value = entry.contentRect.width;\n height.value = entry.contentRect.height;\n }\n }\n },\n options\n );\n tryOnMounted(() => {\n const ele = unrefElement(target);\n if (ele) {\n width.value = \"offsetWidth\" in ele ? ele.offsetWidth : initialSize.width;\n height.value = \"offsetHeight\" in ele ? ele.offsetHeight : initialSize.height;\n }\n });\n const stop2 = watch(\n () => unrefElement(target),\n (ele) => {\n width.value = ele ? initialSize.width : 0;\n height.value = ele ? initialSize.height : 0;\n }\n );\n function stop() {\n stop1();\n stop2();\n }\n return {\n width,\n height,\n stop\n };\n}\n\nfunction useIntersectionObserver(target, callback, options = {}) {\n const {\n root,\n rootMargin = \"0px\",\n threshold = 0,\n window = defaultWindow,\n immediate = true\n } = options;\n const isSupported = useSupported(() => window && \"IntersectionObserver\" in window);\n const targets = computed(() => {\n const _target = toValue(target);\n return toArray(_target).map(unrefElement).filter(notNullish);\n });\n let cleanup = noop;\n const isActive = shallowRef(immediate);\n const stopWatch = isSupported.value ? watch(\n () => [targets.value, unrefElement(root), isActive.value],\n ([targets2, root2]) => {\n cleanup();\n if (!isActive.value)\n return;\n if (!targets2.length)\n return;\n const observer = new IntersectionObserver(\n callback,\n {\n root: unrefElement(root2),\n rootMargin,\n threshold\n }\n );\n targets2.forEach((el) => el && observer.observe(el));\n cleanup = () => {\n observer.disconnect();\n cleanup = noop;\n };\n },\n { immediate, flush: \"post\" }\n ) : noop;\n const stop = () => {\n cleanup();\n stopWatch();\n isActive.value = false;\n };\n tryOnScopeDispose(stop);\n return {\n isSupported,\n isActive,\n pause() {\n cleanup();\n isActive.value = false;\n },\n resume() {\n isActive.value = true;\n },\n stop\n };\n}\n\nfunction useElementVisibility(element, options = {}) {\n const {\n window = defaultWindow,\n scrollTarget,\n threshold = 0,\n rootMargin,\n once = false\n } = options;\n const elementIsVisible = shallowRef(false);\n const { stop } = useIntersectionObserver(\n element,\n (intersectionObserverEntries) => {\n let isIntersecting = elementIsVisible.value;\n let latestTime = 0;\n for (const entry of intersectionObserverEntries) {\n if (entry.time >= latestTime) {\n latestTime = entry.time;\n isIntersecting = entry.isIntersecting;\n }\n }\n elementIsVisible.value = isIntersecting;\n if (once) {\n watchOnce(elementIsVisible, () => {\n stop();\n });\n }\n },\n {\n root: scrollTarget,\n window,\n threshold,\n rootMargin: toValue(rootMargin)\n }\n );\n return elementIsVisible;\n}\n\nconst events = /* @__PURE__ */ new Map();\n\nfunction useEventBus(key) {\n const scope = getCurrentScope();\n function on(listener) {\n var _a;\n const listeners = events.get(key) || /* @__PURE__ */ new Set();\n listeners.add(listener);\n events.set(key, listeners);\n const _off = () => off(listener);\n (_a = scope == null ? void 0 : scope.cleanups) == null ? void 0 : _a.push(_off);\n return _off;\n }\n function once(listener) {\n function _listener(...args) {\n off(_listener);\n listener(...args);\n }\n return on(_listener);\n }\n function off(listener) {\n const listeners = events.get(key);\n if (!listeners)\n return;\n listeners.delete(listener);\n if (!listeners.size)\n reset();\n }\n function reset() {\n events.delete(key);\n }\n function emit(event, payload) {\n var _a;\n (_a = events.get(key)) == null ? void 0 : _a.forEach((v) => v(event, payload));\n }\n return { on, once, off, emit, reset };\n}\n\nfunction resolveNestedOptions$1(options) {\n if (options === true)\n return {};\n return options;\n}\nfunction useEventSource(url, events = [], options = {}) {\n const event = shallowRef(null);\n const data = shallowRef(null);\n const status = shallowRef(\"CONNECTING\");\n const eventSource = ref(null);\n const error = shallowRef(null);\n const urlRef = toRef(url);\n const lastEventId = shallowRef(null);\n let explicitlyClosed = false;\n let retried = 0;\n const {\n withCredentials = false,\n immediate = true,\n autoConnect = true,\n autoReconnect\n } = options;\n const close = () => {\n if (isClient && eventSource.value) {\n eventSource.value.close();\n eventSource.value = null;\n status.value = \"CLOSED\";\n explicitlyClosed = true;\n }\n };\n const _init = () => {\n if (explicitlyClosed || typeof urlRef.value === \"undefined\")\n return;\n const es = new EventSource(urlRef.value, { withCredentials });\n status.value = \"CONNECTING\";\n eventSource.value = es;\n es.onopen = () => {\n status.value = \"OPEN\";\n error.value = null;\n };\n es.onerror = (e) => {\n status.value = \"CLOSED\";\n error.value = e;\n if (es.readyState === 2 && !explicitlyClosed && autoReconnect) {\n es.close();\n const {\n retries = -1,\n delay = 1e3,\n onFailed\n } = resolveNestedOptions$1(autoReconnect);\n retried += 1;\n if (typeof retries === \"number\" && (retries < 0 || retried < retries))\n setTimeout(_init, delay);\n else if (typeof retries === \"function\" && retries())\n setTimeout(_init, delay);\n else\n onFailed == null ? void 0 : onFailed();\n }\n };\n es.onmessage = (e) => {\n event.value = null;\n data.value = e.data;\n lastEventId.value = e.lastEventId;\n };\n for (const event_name of events) {\n useEventListener(es, event_name, (e) => {\n event.value = event_name;\n data.value = e.data || null;\n }, { passive: true });\n }\n };\n const open = () => {\n if (!isClient)\n return;\n close();\n explicitlyClosed = false;\n retried = 0;\n _init();\n };\n if (immediate)\n open();\n if (autoConnect)\n watch(urlRef, open);\n tryOnScopeDispose(close);\n return {\n eventSource,\n event,\n data,\n status,\n error,\n open,\n close,\n lastEventId\n };\n}\n\nfunction useEyeDropper(options = {}) {\n const { initialValue = \"\" } = options;\n const isSupported = useSupported(() => typeof window !== \"undefined\" && \"EyeDropper\" in window);\n const sRGBHex = shallowRef(initialValue);\n async function open(openOptions) {\n if (!isSupported.value)\n return;\n const eyeDropper = new window.EyeDropper();\n const result = await eyeDropper.open(openOptions);\n sRGBHex.value = result.sRGBHex;\n return result;\n }\n return { isSupported, sRGBHex, open };\n}\n\nfunction useFavicon(newIcon = null, options = {}) {\n const {\n baseUrl = \"\",\n rel = \"icon\",\n document = defaultDocument\n } = options;\n const favicon = toRef(newIcon);\n const applyIcon = (icon) => {\n const elements = document == null ? void 0 : document.head.querySelectorAll(`link[rel*=\"${rel}\"]`);\n if (!elements || elements.length === 0) {\n const link = document == null ? void 0 : document.createElement(\"link\");\n if (link) {\n link.rel = rel;\n link.href = `${baseUrl}${icon}`;\n link.type = `image/${icon.split(\".\").pop()}`;\n document == null ? void 0 : document.head.append(link);\n }\n return;\n }\n elements == null ? void 0 : elements.forEach((el) => el.href = `${baseUrl}${icon}`);\n };\n watch(\n favicon,\n (i, o) => {\n if (typeof i === \"string\" && i !== o)\n applyIcon(i);\n },\n { immediate: true }\n );\n return favicon;\n}\n\nconst payloadMapping = {\n json: \"application/json\",\n text: \"text/plain\"\n};\nfunction isFetchOptions(obj) {\n return obj && containsProp(obj, \"immediate\", \"refetch\", \"initialData\", \"timeout\", \"beforeFetch\", \"afterFetch\", \"onFetchError\", \"fetch\", \"updateDataOnError\");\n}\nconst reAbsolute = /^(?:[a-z][a-z\\d+\\-.]*:)?\\/\\//i;\nfunction isAbsoluteURL(url) {\n return reAbsolute.test(url);\n}\nfunction headersToObject(headers) {\n if (typeof Headers !== \"undefined\" && headers instanceof Headers)\n return Object.fromEntries(headers.entries());\n return headers;\n}\nfunction combineCallbacks(combination, ...callbacks) {\n if (combination === \"overwrite\") {\n return async (ctx) => {\n let callback;\n for (let i = callbacks.length - 1; i >= 0; i--) {\n if (callbacks[i] != null) {\n callback = callbacks[i];\n break;\n }\n }\n if (callback)\n return { ...ctx, ...await callback(ctx) };\n return ctx;\n };\n } else {\n return async (ctx) => {\n for (const callback of callbacks) {\n if (callback)\n ctx = { ...ctx, ...await callback(ctx) };\n }\n return ctx;\n };\n }\n}\nfunction createFetch(config = {}) {\n const _combination = config.combination || \"chain\";\n const _options = config.options || {};\n const _fetchOptions = config.fetchOptions || {};\n function useFactoryFetch(url, ...args) {\n const computedUrl = computed(() => {\n const baseUrl = toValue(config.baseUrl);\n const targetUrl = toValue(url);\n return baseUrl && !isAbsoluteURL(targetUrl) ? joinPaths(baseUrl, targetUrl) : targetUrl;\n });\n let options = _options;\n let fetchOptions = _fetchOptions;\n if (args.length > 0) {\n if (isFetchOptions(args[0])) {\n options = {\n ...options,\n ...args[0],\n beforeFetch: combineCallbacks(_combination, _options.beforeFetch, args[0].beforeFetch),\n afterFetch: combineCallbacks(_combination, _options.afterFetch, args[0].afterFetch),\n onFetchError: combineCallbacks(_combination, _options.onFetchError, args[0].onFetchError)\n };\n } else {\n fetchOptions = {\n ...fetchOptions,\n ...args[0],\n headers: {\n ...headersToObject(fetchOptions.headers) || {},\n ...headersToObject(args[0].headers) || {}\n }\n };\n }\n }\n if (args.length > 1 && isFetchOptions(args[1])) {\n options = {\n ...options,\n ...args[1],\n beforeFetch: combineCallbacks(_combination, _options.beforeFetch, args[1].beforeFetch),\n afterFetch: combineCallbacks(_combination, _options.afterFetch, args[1].afterFetch),\n onFetchError: combineCallbacks(_combination, _options.onFetchError, args[1].onFetchError)\n };\n }\n return useFetch(computedUrl, fetchOptions, options);\n }\n return useFactoryFetch;\n}\nfunction useFetch(url, ...args) {\n var _a;\n const supportsAbort = typeof AbortController === \"function\";\n let fetchOptions = {};\n let options = {\n immediate: true,\n refetch: false,\n timeout: 0,\n updateDataOnError: false\n };\n const config = {\n method: \"GET\",\n type: \"text\",\n payload: void 0\n };\n if (args.length > 0) {\n if (isFetchOptions(args[0]))\n options = { ...options, ...args[0] };\n else\n fetchOptions = args[0];\n }\n if (args.length > 1) {\n if (isFetchOptions(args[1]))\n options = { ...options, ...args[1] };\n }\n const {\n fetch = (_a = defaultWindow) == null ? void 0 : _a.fetch,\n initialData,\n timeout\n } = options;\n const responseEvent = createEventHook();\n const errorEvent = createEventHook();\n const finallyEvent = createEventHook();\n const isFinished = shallowRef(false);\n const isFetching = shallowRef(false);\n const aborted = shallowRef(false);\n const statusCode = shallowRef(null);\n const response = shallowRef(null);\n const error = shallowRef(null);\n const data = shallowRef(initialData || null);\n const canAbort = computed(() => supportsAbort && isFetching.value);\n let controller;\n let timer;\n const abort = () => {\n if (supportsAbort) {\n controller == null ? void 0 : controller.abort();\n controller = new AbortController();\n controller.signal.onabort = () => aborted.value = true;\n fetchOptions = {\n ...fetchOptions,\n signal: controller.signal\n };\n }\n };\n const loading = (isLoading) => {\n isFetching.value = isLoading;\n isFinished.value = !isLoading;\n };\n if (timeout)\n timer = useTimeoutFn(abort, timeout, { immediate: false });\n let executeCounter = 0;\n const execute = async (throwOnFailed = false) => {\n var _a2, _b;\n abort();\n loading(true);\n error.value = null;\n statusCode.value = null;\n aborted.value = false;\n executeCounter += 1;\n const currentExecuteCounter = executeCounter;\n const defaultFetchOptions = {\n method: config.method,\n headers: {}\n };\n const payload = toValue(config.payload);\n if (payload) {\n const headers = headersToObject(defaultFetchOptions.headers);\n const proto = Object.getPrototypeOf(payload);\n if (!config.payloadType && payload && (proto === Object.prototype || Array.isArray(proto)) && !(payload instanceof FormData))\n config.payloadType = \"json\";\n if (config.payloadType)\n headers[\"Content-Type\"] = (_a2 = payloadMapping[config.payloadType]) != null ? _a2 : config.payloadType;\n defaultFetchOptions.body = config.payloadType === \"json\" ? JSON.stringify(payload) : payload;\n }\n let isCanceled = false;\n const context = {\n url: toValue(url),\n options: {\n ...defaultFetchOptions,\n ...fetchOptions\n },\n cancel: () => {\n isCanceled = true;\n }\n };\n if (options.beforeFetch)\n Object.assign(context, await options.beforeFetch(context));\n if (isCanceled || !fetch) {\n loading(false);\n return Promise.resolve(null);\n }\n let responseData = null;\n if (timer)\n timer.start();\n return fetch(\n context.url,\n {\n ...defaultFetchOptions,\n ...context.options,\n headers: {\n ...headersToObject(defaultFetchOptions.headers),\n ...headersToObject((_b = context.options) == null ? void 0 : _b.headers)\n }\n }\n ).then(async (fetchResponse) => {\n response.value = fetchResponse;\n statusCode.value = fetchResponse.status;\n responseData = await fetchResponse.clone()[config.type]();\n if (!fetchResponse.ok) {\n data.value = initialData || null;\n throw new Error(fetchResponse.statusText);\n }\n if (options.afterFetch) {\n ({ data: responseData } = await options.afterFetch({\n data: responseData,\n response: fetchResponse,\n context,\n execute\n }));\n }\n data.value = responseData;\n responseEvent.trigger(fetchResponse);\n return fetchResponse;\n }).catch(async (fetchError) => {\n let errorData = fetchError.message || fetchError.name;\n if (options.onFetchError) {\n ({ error: errorData, data: responseData } = await options.onFetchError({\n data: responseData,\n error: fetchError,\n response: response.value,\n context,\n execute\n }));\n }\n error.value = errorData;\n if (options.updateDataOnError)\n data.value = responseData;\n errorEvent.trigger(fetchError);\n if (throwOnFailed)\n throw fetchError;\n return null;\n }).finally(() => {\n if (currentExecuteCounter === executeCounter)\n loading(false);\n if (timer)\n timer.stop();\n finallyEvent.trigger(null);\n });\n };\n const refetch = toRef(options.refetch);\n watch(\n [\n refetch,\n toRef(url)\n ],\n ([refetch2]) => refetch2 && execute(),\n { deep: true }\n );\n const shell = {\n isFinished: readonly(isFinished),\n isFetching: readonly(isFetching),\n statusCode,\n response,\n error,\n data,\n canAbort,\n aborted,\n abort,\n execute,\n onFetchResponse: responseEvent.on,\n onFetchError: errorEvent.on,\n onFetchFinally: finallyEvent.on,\n // method\n get: setMethod(\"GET\"),\n put: setMethod(\"PUT\"),\n post: setMethod(\"POST\"),\n delete: setMethod(\"DELETE\"),\n patch: setMethod(\"PATCH\"),\n head: setMethod(\"HEAD\"),\n options: setMethod(\"OPTIONS\"),\n // type\n json: setType(\"json\"),\n text: setType(\"text\"),\n blob: setType(\"blob\"),\n arrayBuffer: setType(\"arrayBuffer\"),\n formData: setType(\"formData\")\n };\n function setMethod(method) {\n return (payload, payloadType) => {\n if (!isFetching.value) {\n config.method = method;\n config.payload = payload;\n config.payloadType = payloadType;\n if (isRef(config.payload)) {\n watch(\n [\n refetch,\n toRef(config.payload)\n ],\n ([refetch2]) => refetch2 && execute(),\n { deep: true }\n );\n }\n return {\n ...shell,\n then(onFulfilled, onRejected) {\n return waitUntilFinished().then(onFulfilled, onRejected);\n }\n };\n }\n return void 0;\n };\n }\n function waitUntilFinished() {\n return new Promise((resolve, reject) => {\n until(isFinished).toBe(true).then(() => resolve(shell)).catch(reject);\n });\n }\n function setType(type) {\n return () => {\n if (!isFetching.value) {\n config.type = type;\n return {\n ...shell,\n then(onFulfilled, onRejected) {\n return waitUntilFinished().then(onFulfilled, onRejected);\n }\n };\n }\n return void 0;\n };\n }\n if (options.immediate)\n Promise.resolve().then(() => execute());\n return {\n ...shell,\n then(onFulfilled, onRejected) {\n return waitUntilFinished().then(onFulfilled, onRejected);\n }\n };\n}\nfunction joinPaths(start, end) {\n if (!start.endsWith(\"/\") && !end.startsWith(\"/\")) {\n return `${start}/${end}`;\n }\n if (start.endsWith(\"/\") && end.startsWith(\"/\")) {\n return `${start.slice(0, -1)}${end}`;\n }\n return `${start}${end}`;\n}\n\nconst DEFAULT_OPTIONS = {\n multiple: true,\n accept: \"*\",\n reset: false,\n directory: false\n};\nfunction prepareInitialFiles(files) {\n if (!files)\n return null;\n if (files instanceof FileList)\n return files;\n const dt = new DataTransfer();\n for (const file of files) {\n dt.items.add(file);\n }\n return dt.files;\n}\nfunction useFileDialog(options = {}) {\n const {\n document = defaultDocument\n } = options;\n const files = ref(prepareInitialFiles(options.initialFiles));\n const { on: onChange, trigger: changeTrigger } = createEventHook();\n const { on: onCancel, trigger: cancelTrigger } = createEventHook();\n let input;\n if (document) {\n input = document.createElement(\"input\");\n input.type = \"file\";\n input.onchange = (event) => {\n const result = event.target;\n files.value = result.files;\n changeTrigger(files.value);\n };\n input.oncancel = () => {\n cancelTrigger();\n };\n }\n const reset = () => {\n files.value = null;\n if (input && input.value) {\n input.value = \"\";\n changeTrigger(null);\n }\n };\n const open = (localOptions) => {\n if (!input)\n return;\n const _options = {\n ...DEFAULT_OPTIONS,\n ...options,\n ...localOptions\n };\n input.multiple = _options.multiple;\n input.accept = _options.accept;\n input.webkitdirectory = _options.directory;\n if (hasOwn(_options, \"capture\"))\n input.capture = _options.capture;\n if (_options.reset)\n reset();\n input.click();\n };\n return {\n files: readonly(files),\n open,\n reset,\n onCancel,\n onChange\n };\n}\n\nfunction useFileSystemAccess(options = {}) {\n const {\n window: _window = defaultWindow,\n dataType = \"Text\"\n } = options;\n const window = _window;\n const isSupported = useSupported(() => window && \"showSaveFilePicker\" in window && \"showOpenFilePicker\" in window);\n const fileHandle = shallowRef();\n const data = shallowRef();\n const file = shallowRef();\n const fileName = computed(() => {\n var _a, _b;\n return (_b = (_a = file.value) == null ? void 0 : _a.name) != null ? _b : \"\";\n });\n const fileMIME = computed(() => {\n var _a, _b;\n return (_b = (_a = file.value) == null ? void 0 : _a.type) != null ? _b : \"\";\n });\n const fileSize = computed(() => {\n var _a, _b;\n return (_b = (_a = file.value) == null ? void 0 : _a.size) != null ? _b : 0;\n });\n const fileLastModified = computed(() => {\n var _a, _b;\n return (_b = (_a = file.value) == null ? void 0 : _a.lastModified) != null ? _b : 0;\n });\n async function open(_options = {}) {\n if (!isSupported.value)\n return;\n const [handle] = await window.showOpenFilePicker({ ...toValue(options), ..._options });\n fileHandle.value = handle;\n await updateData();\n }\n async function create(_options = {}) {\n if (!isSupported.value)\n return;\n fileHandle.value = await window.showSaveFilePicker({ ...options, ..._options });\n data.value = void 0;\n await updateData();\n }\n async function save(_options = {}) {\n if (!isSupported.value)\n return;\n if (!fileHandle.value)\n return saveAs(_options);\n if (data.value) {\n const writableStream = await fileHandle.value.createWritable();\n await writableStream.write(data.value);\n await writableStream.close();\n }\n await updateFile();\n }\n async function saveAs(_options = {}) {\n if (!isSupported.value)\n return;\n fileHandle.value = await window.showSaveFilePicker({ ...options, ..._options });\n if (data.value) {\n const writableStream = await fileHandle.value.createWritable();\n await writableStream.write(data.value);\n await writableStream.close();\n }\n await updateFile();\n }\n async function updateFile() {\n var _a;\n file.value = await ((_a = fileHandle.value) == null ? void 0 : _a.getFile());\n }\n async function updateData() {\n var _a, _b;\n await updateFile();\n const type = toValue(dataType);\n if (type === \"Text\")\n data.value = await ((_a = file.value) == null ? void 0 : _a.text());\n else if (type === \"ArrayBuffer\")\n data.value = await ((_b = file.value) == null ? void 0 : _b.arrayBuffer());\n else if (type === \"Blob\")\n data.value = file.value;\n }\n watch(() => toValue(dataType), updateData);\n return {\n isSupported,\n data,\n file,\n fileName,\n fileMIME,\n fileSize,\n fileLastModified,\n open,\n create,\n save,\n saveAs,\n updateData\n };\n}\n\nfunction useFocus(target, options = {}) {\n const { initialValue = false, focusVisible = false, preventScroll = false } = options;\n const innerFocused = shallowRef(false);\n const targetElement = computed(() => unrefElement(target));\n const listenerOptions = { passive: true };\n useEventListener(targetElement, \"focus\", (event) => {\n var _a, _b;\n if (!focusVisible || ((_b = (_a = event.target).matches) == null ? void 0 : _b.call(_a, \":focus-visible\")))\n innerFocused.value = true;\n }, listenerOptions);\n useEventListener(targetElement, \"blur\", () => innerFocused.value = false, listenerOptions);\n const focused = computed({\n get: () => innerFocused.value,\n set(value) {\n var _a, _b;\n if (!value && innerFocused.value)\n (_a = targetElement.value) == null ? void 0 : _a.blur();\n else if (value && !innerFocused.value)\n (_b = targetElement.value) == null ? void 0 : _b.focus({ preventScroll });\n }\n });\n watch(\n targetElement,\n () => {\n focused.value = initialValue;\n },\n { immediate: true, flush: \"post\" }\n );\n return { focused };\n}\n\nconst EVENT_FOCUS_IN = \"focusin\";\nconst EVENT_FOCUS_OUT = \"focusout\";\nconst PSEUDO_CLASS_FOCUS_WITHIN = \":focus-within\";\nfunction useFocusWithin(target, options = {}) {\n const { window = defaultWindow } = options;\n const targetElement = computed(() => unrefElement(target));\n const _focused = shallowRef(false);\n const focused = computed(() => _focused.value);\n const activeElement = useActiveElement(options);\n if (!window || !activeElement.value) {\n return { focused };\n }\n const listenerOptions = { passive: true };\n useEventListener(targetElement, EVENT_FOCUS_IN, () => _focused.value = true, listenerOptions);\n useEventListener(targetElement, EVENT_FOCUS_OUT, () => {\n var _a, _b, _c;\n return _focused.value = (_c = (_b = (_a = targetElement.value) == null ? void 0 : _a.matches) == null ? void 0 : _b.call(_a, PSEUDO_CLASS_FOCUS_WITHIN)) != null ? _c : false;\n }, listenerOptions);\n return { focused };\n}\n\nfunction useFps(options) {\n var _a;\n const fps = shallowRef(0);\n if (typeof performance === \"undefined\")\n return fps;\n const every = (_a = options == null ? void 0 : options.every) != null ? _a : 10;\n let last = performance.now();\n let ticks = 0;\n useRafFn(() => {\n ticks += 1;\n if (ticks >= every) {\n const now = performance.now();\n const diff = now - last;\n fps.value = Math.round(1e3 / (diff / ticks));\n last = now;\n ticks = 0;\n }\n });\n return fps;\n}\n\nconst eventHandlers = [\n \"fullscreenchange\",\n \"webkitfullscreenchange\",\n \"webkitendfullscreen\",\n \"mozfullscreenchange\",\n \"MSFullscreenChange\"\n];\nfunction useFullscreen(target, options = {}) {\n const {\n document = defaultDocument,\n autoExit = false\n } = options;\n const targetRef = computed(() => {\n var _a;\n return (_a = unrefElement(target)) != null ? _a : document == null ? void 0 : document.documentElement;\n });\n const isFullscreen = shallowRef(false);\n const requestMethod = computed(() => {\n return [\n \"requestFullscreen\",\n \"webkitRequestFullscreen\",\n \"webkitEnterFullscreen\",\n \"webkitEnterFullScreen\",\n \"webkitRequestFullScreen\",\n \"mozRequestFullScreen\",\n \"msRequestFullscreen\"\n ].find((m) => document && m in document || targetRef.value && m in targetRef.value);\n });\n const exitMethod = computed(() => {\n return [\n \"exitFullscreen\",\n \"webkitExitFullscreen\",\n \"webkitExitFullScreen\",\n \"webkitCancelFullScreen\",\n \"mozCancelFullScreen\",\n \"msExitFullscreen\"\n ].find((m) => document && m in document || targetRef.value && m in targetRef.value);\n });\n const fullscreenEnabled = computed(() => {\n return [\n \"fullScreen\",\n \"webkitIsFullScreen\",\n \"webkitDisplayingFullscreen\",\n \"mozFullScreen\",\n \"msFullscreenElement\"\n ].find((m) => document && m in document || targetRef.value && m in targetRef.value);\n });\n const fullscreenElementMethod = [\n \"fullscreenElement\",\n \"webkitFullscreenElement\",\n \"mozFullScreenElement\",\n \"msFullscreenElement\"\n ].find((m) => document && m in document);\n const isSupported = useSupported(() => targetRef.value && document && requestMethod.value !== void 0 && exitMethod.value !== void 0 && fullscreenEnabled.value !== void 0);\n const isCurrentElementFullScreen = () => {\n if (fullscreenElementMethod)\n return (document == null ? void 0 : document[fullscreenElementMethod]) === targetRef.value;\n return false;\n };\n const isElementFullScreen = () => {\n if (fullscreenEnabled.value) {\n if (document && document[fullscreenEnabled.value] != null) {\n return document[fullscreenEnabled.value];\n } else {\n const target2 = targetRef.value;\n if ((target2 == null ? void 0 : target2[fullscreenEnabled.value]) != null) {\n return Boolean(target2[fullscreenEnabled.value]);\n }\n }\n }\n return false;\n };\n async function exit() {\n if (!isSupported.value || !isFullscreen.value)\n return;\n if (exitMethod.value) {\n if ((document == null ? void 0 : document[exitMethod.value]) != null) {\n await document[exitMethod.value]();\n } else {\n const target2 = targetRef.value;\n if ((target2 == null ? void 0 : target2[exitMethod.value]) != null)\n await target2[exitMethod.value]();\n }\n }\n isFullscreen.value = false;\n }\n async function enter() {\n if (!isSupported.value || isFullscreen.value)\n return;\n if (isElementFullScreen())\n await exit();\n const target2 = targetRef.value;\n if (requestMethod.value && (target2 == null ? void 0 : target2[requestMethod.value]) != null) {\n await target2[requestMethod.value]();\n isFullscreen.value = true;\n }\n }\n async function toggle() {\n await (isFullscreen.value ? exit() : enter());\n }\n const handlerCallback = () => {\n const isElementFullScreenValue = isElementFullScreen();\n if (!isElementFullScreenValue || isElementFullScreenValue && isCurrentElementFullScreen())\n isFullscreen.value = isElementFullScreenValue;\n };\n const listenerOptions = { capture: false, passive: true };\n useEventListener(document, eventHandlers, handlerCallback, listenerOptions);\n useEventListener(() => unrefElement(targetRef), eventHandlers, handlerCallback, listenerOptions);\n if (autoExit)\n tryOnScopeDispose(exit);\n return {\n isSupported,\n isFullscreen,\n enter,\n exit,\n toggle\n };\n}\n\nfunction mapGamepadToXbox360Controller(gamepad) {\n return computed(() => {\n if (gamepad.value) {\n return {\n buttons: {\n a: gamepad.value.buttons[0],\n b: gamepad.value.buttons[1],\n x: gamepad.value.buttons[2],\n y: gamepad.value.buttons[3]\n },\n bumper: {\n left: gamepad.value.buttons[4],\n right: gamepad.value.buttons[5]\n },\n triggers: {\n left: gamepad.value.buttons[6],\n right: gamepad.value.buttons[7]\n },\n stick: {\n left: {\n horizontal: gamepad.value.axes[0],\n vertical: gamepad.value.axes[1],\n button: gamepad.value.buttons[10]\n },\n right: {\n horizontal: gamepad.value.axes[2],\n vertical: gamepad.value.axes[3],\n button: gamepad.value.buttons[11]\n }\n },\n dpad: {\n up: gamepad.value.buttons[12],\n down: gamepad.value.buttons[13],\n left: gamepad.value.buttons[14],\n right: gamepad.value.buttons[15]\n },\n back: gamepad.value.buttons[8],\n start: gamepad.value.buttons[9]\n };\n }\n return null;\n });\n}\nfunction useGamepad(options = {}) {\n const {\n navigator = defaultNavigator\n } = options;\n const isSupported = useSupported(() => navigator && \"getGamepads\" in navigator);\n const gamepads = ref([]);\n const onConnectedHook = createEventHook();\n const onDisconnectedHook = createEventHook();\n const stateFromGamepad = (gamepad) => {\n const hapticActuators = [];\n const vibrationActuator = \"vibrationActuator\" in gamepad ? gamepad.vibrationActuator : null;\n if (vibrationActuator)\n hapticActuators.push(vibrationActuator);\n if (gamepad.hapticActuators)\n hapticActuators.push(...gamepad.hapticActuators);\n return {\n id: gamepad.id,\n index: gamepad.index,\n connected: gamepad.connected,\n mapping: gamepad.mapping,\n timestamp: gamepad.timestamp,\n vibrationActuator: gamepad.vibrationActuator,\n hapticActuators,\n axes: gamepad.axes.map((axes) => axes),\n buttons: gamepad.buttons.map((button) => ({ pressed: button.pressed, touched: button.touched, value: button.value }))\n };\n };\n const updateGamepadState = () => {\n const _gamepads = (navigator == null ? void 0 : navigator.getGamepads()) || [];\n for (const gamepad of _gamepads) {\n if (gamepad && gamepads.value[gamepad.index])\n gamepads.value[gamepad.index] = stateFromGamepad(gamepad);\n }\n };\n const { isActive, pause, resume } = useRafFn(updateGamepadState);\n const onGamepadConnected = (gamepad) => {\n if (!gamepads.value.some(({ index }) => index === gamepad.index)) {\n gamepads.value.push(stateFromGamepad(gamepad));\n onConnectedHook.trigger(gamepad.index);\n }\n resume();\n };\n const onGamepadDisconnected = (gamepad) => {\n gamepads.value = gamepads.value.filter((x) => x.index !== gamepad.index);\n onDisconnectedHook.trigger(gamepad.index);\n };\n const listenerOptions = { passive: true };\n useEventListener(\"gamepadconnected\", (e) => onGamepadConnected(e.gamepad), listenerOptions);\n useEventListener(\"gamepaddisconnected\", (e) => onGamepadDisconnected(e.gamepad), listenerOptions);\n tryOnMounted(() => {\n const _gamepads = (navigator == null ? void 0 : navigator.getGamepads()) || [];\n for (const gamepad of _gamepads) {\n if (gamepad && gamepads.value[gamepad.index])\n onGamepadConnected(gamepad);\n }\n });\n pause();\n return {\n isSupported,\n onConnected: onConnectedHook.on,\n onDisconnected: onDisconnectedHook.on,\n gamepads,\n pause,\n resume,\n isActive\n };\n}\n\nfunction useGeolocation(options = {}) {\n const {\n enableHighAccuracy = true,\n maximumAge = 3e4,\n timeout = 27e3,\n navigator = defaultNavigator,\n immediate = true\n } = options;\n const isSupported = useSupported(() => navigator && \"geolocation\" in navigator);\n const locatedAt = shallowRef(null);\n const error = shallowRef(null);\n const coords = ref({\n accuracy: 0,\n latitude: Number.POSITIVE_INFINITY,\n longitude: Number.POSITIVE_INFINITY,\n altitude: null,\n altitudeAccuracy: null,\n heading: null,\n speed: null\n });\n function updatePosition(position) {\n locatedAt.value = position.timestamp;\n coords.value = position.coords;\n error.value = null;\n }\n let watcher;\n function resume() {\n if (isSupported.value) {\n watcher = navigator.geolocation.watchPosition(\n updatePosition,\n (err) => error.value = err,\n {\n enableHighAccuracy,\n maximumAge,\n timeout\n }\n );\n }\n }\n if (immediate)\n resume();\n function pause() {\n if (watcher && navigator)\n navigator.geolocation.clearWatch(watcher);\n }\n tryOnScopeDispose(() => {\n pause();\n });\n return {\n isSupported,\n coords,\n locatedAt,\n error,\n resume,\n pause\n };\n}\n\nconst defaultEvents$1 = [\"mousemove\", \"mousedown\", \"resize\", \"keydown\", \"touchstart\", \"wheel\"];\nconst oneMinute = 6e4;\nfunction useIdle(timeout = oneMinute, options = {}) {\n const {\n initialState = false,\n listenForVisibilityChange = true,\n events = defaultEvents$1,\n window = defaultWindow,\n eventFilter = throttleFilter(50)\n } = options;\n const idle = shallowRef(initialState);\n const lastActive = shallowRef(timestamp());\n let timer;\n const reset = () => {\n idle.value = false;\n clearTimeout(timer);\n timer = setTimeout(() => idle.value = true, timeout);\n };\n const onEvent = createFilterWrapper(\n eventFilter,\n () => {\n lastActive.value = timestamp();\n reset();\n }\n );\n if (window) {\n const document = window.document;\n const listenerOptions = { passive: true };\n for (const event of events)\n useEventListener(window, event, onEvent, listenerOptions);\n if (listenForVisibilityChange) {\n useEventListener(document, \"visibilitychange\", () => {\n if (!document.hidden)\n onEvent();\n }, listenerOptions);\n }\n reset();\n }\n return {\n idle,\n lastActive,\n reset\n };\n}\n\nasync function loadImage(options) {\n return new Promise((resolve, reject) => {\n const img = new Image();\n const { src, srcset, sizes, class: clazz, loading, crossorigin, referrerPolicy, width, height, decoding, fetchPriority, ismap, usemap } = options;\n img.src = src;\n if (srcset != null)\n img.srcset = srcset;\n if (sizes != null)\n img.sizes = sizes;\n if (clazz != null)\n img.className = clazz;\n if (loading != null)\n img.loading = loading;\n if (crossorigin != null)\n img.crossOrigin = crossorigin;\n if (referrerPolicy != null)\n img.referrerPolicy = referrerPolicy;\n if (width != null)\n img.width = width;\n if (height != null)\n img.height = height;\n if (decoding != null)\n img.decoding = decoding;\n if (fetchPriority != null)\n img.fetchPriority = fetchPriority;\n if (ismap != null)\n img.isMap = ismap;\n if (usemap != null)\n img.useMap = usemap;\n img.onload = () => resolve(img);\n img.onerror = reject;\n });\n}\nfunction useImage(options, asyncStateOptions = {}) {\n const state = useAsyncState(\n () => loadImage(toValue(options)),\n void 0,\n {\n resetOnExecute: true,\n ...asyncStateOptions\n }\n );\n watch(\n () => toValue(options),\n () => state.execute(asyncStateOptions.delay),\n { deep: true }\n );\n return state;\n}\n\nfunction resolveElement(el) {\n if (typeof Window !== \"undefined\" && el instanceof Window)\n return el.document.documentElement;\n if (typeof Document !== \"undefined\" && el instanceof Document)\n return el.documentElement;\n return el;\n}\n\nconst ARRIVED_STATE_THRESHOLD_PIXELS = 1;\nfunction useScroll(element, options = {}) {\n const {\n throttle = 0,\n idle = 200,\n onStop = noop,\n onScroll = noop,\n offset = {\n left: 0,\n right: 0,\n top: 0,\n bottom: 0\n },\n eventListenerOptions = {\n capture: false,\n passive: true\n },\n behavior = \"auto\",\n window = defaultWindow,\n onError = (e) => {\n console.error(e);\n }\n } = options;\n const internalX = shallowRef(0);\n const internalY = shallowRef(0);\n const x = computed({\n get() {\n return internalX.value;\n },\n set(x2) {\n scrollTo(x2, void 0);\n }\n });\n const y = computed({\n get() {\n return internalY.value;\n },\n set(y2) {\n scrollTo(void 0, y2);\n }\n });\n function scrollTo(_x, _y) {\n var _a, _b, _c, _d;\n if (!window)\n return;\n const _element = toValue(element);\n if (!_element)\n return;\n (_c = _element instanceof Document ? window.document.body : _element) == null ? void 0 : _c.scrollTo({\n top: (_a = toValue(_y)) != null ? _a : y.value,\n left: (_b = toValue(_x)) != null ? _b : x.value,\n behavior: toValue(behavior)\n });\n const scrollContainer = ((_d = _element == null ? void 0 : _element.document) == null ? void 0 : _d.documentElement) || (_element == null ? void 0 : _element.documentElement) || _element;\n if (x != null)\n internalX.value = scrollContainer.scrollLeft;\n if (y != null)\n internalY.value = scrollContainer.scrollTop;\n }\n const isScrolling = shallowRef(false);\n const arrivedState = reactive({\n left: true,\n right: false,\n top: true,\n bottom: false\n });\n const directions = reactive({\n left: false,\n right: false,\n top: false,\n bottom: false\n });\n const onScrollEnd = (e) => {\n if (!isScrolling.value)\n return;\n isScrolling.value = false;\n directions.left = false;\n directions.right = false;\n directions.top = false;\n directions.bottom = false;\n onStop(e);\n };\n const onScrollEndDebounced = useDebounceFn(onScrollEnd, throttle + idle);\n const setArrivedState = (target) => {\n var _a;\n if (!window)\n return;\n const el = ((_a = target == null ? void 0 : target.document) == null ? void 0 : _a.documentElement) || (target == null ? void 0 : target.documentElement) || unrefElement(target);\n const { display, flexDirection, direction } = getComputedStyle(el);\n const directionMultipler = direction === \"rtl\" ? -1 : 1;\n const scrollLeft = el.scrollLeft;\n directions.left = scrollLeft < internalX.value;\n directions.right = scrollLeft > internalX.value;\n const left = Math.abs(scrollLeft * directionMultipler) <= (offset.left || 0);\n const right = Math.abs(scrollLeft * directionMultipler) + el.clientWidth >= el.scrollWidth - (offset.right || 0) - ARRIVED_STATE_THRESHOLD_PIXELS;\n if (display === \"flex\" && flexDirection === \"row-reverse\") {\n arrivedState.left = right;\n arrivedState.right = left;\n } else {\n arrivedState.left = left;\n arrivedState.right = right;\n }\n internalX.value = scrollLeft;\n let scrollTop = el.scrollTop;\n if (target === window.document && !scrollTop)\n scrollTop = window.document.body.scrollTop;\n directions.top = scrollTop < internalY.value;\n directions.bottom = scrollTop > internalY.value;\n const top = Math.abs(scrollTop) <= (offset.top || 0);\n const bottom = Math.abs(scrollTop) + el.clientHeight >= el.scrollHeight - (offset.bottom || 0) - ARRIVED_STATE_THRESHOLD_PIXELS;\n if (display === \"flex\" && flexDirection === \"column-reverse\") {\n arrivedState.top = bottom;\n arrivedState.bottom = top;\n } else {\n arrivedState.top = top;\n arrivedState.bottom = bottom;\n }\n internalY.value = scrollTop;\n };\n const onScrollHandler = (e) => {\n var _a;\n if (!window)\n return;\n const eventTarget = (_a = e.target.documentElement) != null ? _a : e.target;\n setArrivedState(eventTarget);\n isScrolling.value = true;\n onScrollEndDebounced(e);\n onScroll(e);\n };\n useEventListener(\n element,\n \"scroll\",\n throttle ? useThrottleFn(onScrollHandler, throttle, true, false) : onScrollHandler,\n eventListenerOptions\n );\n tryOnMounted(() => {\n try {\n const _element = toValue(element);\n if (!_element)\n return;\n setArrivedState(_element);\n } catch (e) {\n onError(e);\n }\n });\n useEventListener(\n element,\n \"scrollend\",\n onScrollEnd,\n eventListenerOptions\n );\n return {\n x,\n y,\n isScrolling,\n arrivedState,\n directions,\n measure() {\n const _element = toValue(element);\n if (window && _element)\n setArrivedState(_element);\n }\n };\n}\n\nfunction useInfiniteScroll(element, onLoadMore, options = {}) {\n var _a;\n const {\n direction = \"bottom\",\n interval = 100,\n canLoadMore = () => true\n } = options;\n const state = reactive(useScroll(\n element,\n {\n ...options,\n offset: {\n [direction]: (_a = options.distance) != null ? _a : 0,\n ...options.offset\n }\n }\n ));\n const promise = ref();\n const isLoading = computed(() => !!promise.value);\n const observedElement = computed(() => {\n return resolveElement(toValue(element));\n });\n const isElementVisible = useElementVisibility(observedElement);\n function checkAndLoad() {\n state.measure();\n if (!observedElement.value || !isElementVisible.value || !canLoadMore(observedElement.value))\n return;\n const { scrollHeight, clientHeight, scrollWidth, clientWidth } = observedElement.value;\n const isNarrower = direction === \"bottom\" || direction === \"top\" ? scrollHeight <= clientHeight : scrollWidth <= clientWidth;\n if (state.arrivedState[direction] || isNarrower) {\n if (!promise.value) {\n promise.value = Promise.all([\n onLoadMore(state),\n new Promise((resolve) => setTimeout(resolve, interval))\n ]).finally(() => {\n promise.value = null;\n nextTick(() => checkAndLoad());\n });\n }\n }\n }\n const stop = watch(\n () => [state.arrivedState[direction], isElementVisible.value],\n checkAndLoad,\n { immediate: true }\n );\n tryOnUnmounted(stop);\n return {\n isLoading,\n reset() {\n nextTick(() => checkAndLoad());\n }\n };\n}\n\nconst defaultEvents = [\"mousedown\", \"mouseup\", \"keydown\", \"keyup\"];\nfunction useKeyModifier(modifier, options = {}) {\n const {\n events = defaultEvents,\n document = defaultDocument,\n initial = null\n } = options;\n const state = shallowRef(initial);\n if (document) {\n events.forEach((listenerEvent) => {\n useEventListener(document, listenerEvent, (evt) => {\n if (typeof evt.getModifierState === \"function\")\n state.value = evt.getModifierState(modifier);\n }, { passive: true });\n });\n }\n return state;\n}\n\nfunction useLocalStorage(key, initialValue, options = {}) {\n const { window = defaultWindow } = options;\n return useStorage(key, initialValue, window == null ? void 0 : window.localStorage, options);\n}\n\nconst DefaultMagicKeysAliasMap = {\n ctrl: \"control\",\n command: \"meta\",\n cmd: \"meta\",\n option: \"alt\",\n up: \"arrowup\",\n down: \"arrowdown\",\n left: \"arrowleft\",\n right: \"arrowright\"\n};\n\nfunction useMagicKeys(options = {}) {\n const {\n reactive: useReactive = false,\n target = defaultWindow,\n aliasMap = DefaultMagicKeysAliasMap,\n passive = true,\n onEventFired = noop\n } = options;\n const current = reactive(/* @__PURE__ */ new Set());\n const obj = {\n toJSON() {\n return {};\n },\n current\n };\n const refs = useReactive ? reactive(obj) : obj;\n const metaDeps = /* @__PURE__ */ new Set();\n const usedKeys = /* @__PURE__ */ new Set();\n function setRefs(key, value) {\n if (key in refs) {\n if (useReactive)\n refs[key] = value;\n else\n refs[key].value = value;\n }\n }\n function reset() {\n current.clear();\n for (const key of usedKeys)\n setRefs(key, false);\n }\n function updateRefs(e, value) {\n var _a, _b;\n const key = (_a = e.key) == null ? void 0 : _a.toLowerCase();\n const code = (_b = e.code) == null ? void 0 : _b.toLowerCase();\n const values = [code, key].filter(Boolean);\n if (key) {\n if (value)\n current.add(key);\n else\n current.delete(key);\n }\n for (const key2 of values) {\n usedKeys.add(key2);\n setRefs(key2, value);\n }\n if (key === \"meta\" && !value) {\n metaDeps.forEach((key2) => {\n current.delete(key2);\n setRefs(key2, false);\n });\n metaDeps.clear();\n } else if (typeof e.getModifierState === \"function\" && e.getModifierState(\"Meta\") && value) {\n [...current, ...values].forEach((key2) => metaDeps.add(key2));\n }\n }\n useEventListener(target, \"keydown\", (e) => {\n updateRefs(e, true);\n return onEventFired(e);\n }, { passive });\n useEventListener(target, \"keyup\", (e) => {\n updateRefs(e, false);\n return onEventFired(e);\n }, { passive });\n useEventListener(\"blur\", reset, { passive });\n useEventListener(\"focus\", reset, { passive });\n const proxy = new Proxy(\n refs,\n {\n get(target2, prop, rec) {\n if (typeof prop !== \"string\")\n return Reflect.get(target2, prop, rec);\n prop = prop.toLowerCase();\n if (prop in aliasMap)\n prop = aliasMap[prop];\n if (!(prop in refs)) {\n if (/[+_-]/.test(prop)) {\n const keys = prop.split(/[+_-]/g).map((i) => i.trim());\n refs[prop] = computed(() => keys.map((key) => toValue(proxy[key])).every(Boolean));\n } else {\n refs[prop] = shallowRef(false);\n }\n }\n const r = Reflect.get(target2, prop, rec);\n return useReactive ? toValue(r) : r;\n }\n }\n );\n return proxy;\n}\n\nfunction usingElRef(source, cb) {\n if (toValue(source))\n cb(toValue(source));\n}\nfunction timeRangeToArray(timeRanges) {\n let ranges = [];\n for (let i = 0; i < timeRanges.length; ++i)\n ranges = [...ranges, [timeRanges.start(i), timeRanges.end(i)]];\n return ranges;\n}\nfunction tracksToArray(tracks) {\n return Array.from(tracks).map(({ label, kind, language, mode, activeCues, cues, inBandMetadataTrackDispatchType }, id) => ({ id, label, kind, language, mode, activeCues, cues, inBandMetadataTrackDispatchType }));\n}\nconst defaultOptions = {\n src: \"\",\n tracks: []\n};\nfunction useMediaControls(target, options = {}) {\n target = toRef(target);\n options = {\n ...defaultOptions,\n ...options\n };\n const {\n document = defaultDocument\n } = options;\n const listenerOptions = { passive: true };\n const currentTime = shallowRef(0);\n const duration = shallowRef(0);\n const seeking = shallowRef(false);\n const volume = shallowRef(1);\n const waiting = shallowRef(false);\n const ended = shallowRef(false);\n const playing = shallowRef(false);\n const rate = shallowRef(1);\n const stalled = shallowRef(false);\n const buffered = ref([]);\n const tracks = ref([]);\n const selectedTrack = shallowRef(-1);\n const isPictureInPicture = shallowRef(false);\n const muted = shallowRef(false);\n const supportsPictureInPicture = document && \"pictureInPictureEnabled\" in document;\n const sourceErrorEvent = createEventHook();\n const playbackErrorEvent = createEventHook();\n const disableTrack = (track) => {\n usingElRef(target, (el) => {\n if (track) {\n const id = typeof track === \"number\" ? track : track.id;\n el.textTracks[id].mode = \"disabled\";\n } else {\n for (let i = 0; i < el.textTracks.length; ++i)\n el.textTracks[i].mode = \"disabled\";\n }\n selectedTrack.value = -1;\n });\n };\n const enableTrack = (track, disableTracks = true) => {\n usingElRef(target, (el) => {\n const id = typeof track === \"number\" ? track : track.id;\n if (disableTracks)\n disableTrack();\n el.textTracks[id].mode = \"showing\";\n selectedTrack.value = id;\n });\n };\n const togglePictureInPicture = () => {\n return new Promise((resolve, reject) => {\n usingElRef(target, async (el) => {\n if (supportsPictureInPicture) {\n if (!isPictureInPicture.value) {\n el.requestPictureInPicture().then(resolve).catch(reject);\n } else {\n document.exitPictureInPicture().then(resolve).catch(reject);\n }\n }\n });\n });\n };\n watchEffect(() => {\n if (!document)\n return;\n const el = toValue(target);\n if (!el)\n return;\n const src = toValue(options.src);\n let sources = [];\n if (!src)\n return;\n if (typeof src === \"string\")\n sources = [{ src }];\n else if (Array.isArray(src))\n sources = src;\n else if (isObject(src))\n sources = [src];\n el.querySelectorAll(\"source\").forEach((e) => {\n e.remove();\n });\n sources.forEach(({ src: src2, type, media }) => {\n const source = document.createElement(\"source\");\n source.setAttribute(\"src\", src2);\n source.setAttribute(\"type\", type || \"\");\n source.setAttribute(\"media\", media || \"\");\n useEventListener(source, \"error\", sourceErrorEvent.trigger, listenerOptions);\n el.appendChild(source);\n });\n el.load();\n });\n watch([target, volume], () => {\n const el = toValue(target);\n if (!el)\n return;\n el.volume = volume.value;\n });\n watch([target, muted], () => {\n const el = toValue(target);\n if (!el)\n return;\n el.muted = muted.value;\n });\n watch([target, rate], () => {\n const el = toValue(target);\n if (!el)\n return;\n el.playbackRate = rate.value;\n });\n watchEffect(() => {\n if (!document)\n return;\n const textTracks = toValue(options.tracks);\n const el = toValue(target);\n if (!textTracks || !textTracks.length || !el)\n return;\n el.querySelectorAll(\"track\").forEach((e) => e.remove());\n textTracks.forEach(({ default: isDefault, kind, label, src, srcLang }, i) => {\n const track = document.createElement(\"track\");\n track.default = isDefault || false;\n track.kind = kind;\n track.label = label;\n track.src = src;\n track.srclang = srcLang;\n if (track.default)\n selectedTrack.value = i;\n el.appendChild(track);\n });\n });\n const { ignoreUpdates: ignoreCurrentTimeUpdates } = watchIgnorable(currentTime, (time) => {\n const el = toValue(target);\n if (!el)\n return;\n el.currentTime = time;\n });\n const { ignoreUpdates: ignorePlayingUpdates } = watchIgnorable(playing, (isPlaying) => {\n const el = toValue(target);\n if (!el)\n return;\n if (isPlaying) {\n el.play().catch((e) => {\n playbackErrorEvent.trigger(e);\n throw e;\n });\n } else {\n el.pause();\n }\n });\n useEventListener(\n target,\n \"timeupdate\",\n () => ignoreCurrentTimeUpdates(() => currentTime.value = toValue(target).currentTime),\n listenerOptions\n );\n useEventListener(\n target,\n \"durationchange\",\n () => duration.value = toValue(target).duration,\n listenerOptions\n );\n useEventListener(\n target,\n \"progress\",\n () => buffered.value = timeRangeToArray(toValue(target).buffered),\n listenerOptions\n );\n useEventListener(\n target,\n \"seeking\",\n () => seeking.value = true,\n listenerOptions\n );\n useEventListener(\n target,\n \"seeked\",\n () => seeking.value = false,\n listenerOptions\n );\n useEventListener(\n target,\n [\"waiting\", \"loadstart\"],\n () => {\n waiting.value = true;\n ignorePlayingUpdates(() => playing.value = false);\n },\n listenerOptions\n );\n useEventListener(\n target,\n \"loadeddata\",\n () => waiting.value = false,\n listenerOptions\n );\n useEventListener(\n target,\n \"playing\",\n () => {\n waiting.value = false;\n ended.value = false;\n ignorePlayingUpdates(() => playing.value = true);\n },\n listenerOptions\n );\n useEventListener(\n target,\n \"ratechange\",\n () => rate.value = toValue(target).playbackRate,\n listenerOptions\n );\n useEventListener(\n target,\n \"stalled\",\n () => stalled.value = true,\n listenerOptions\n );\n useEventListener(\n target,\n \"ended\",\n () => ended.value = true,\n listenerOptions\n );\n useEventListener(\n target,\n \"pause\",\n () => ignorePlayingUpdates(() => playing.value = false),\n listenerOptions\n );\n useEventListener(\n target,\n \"play\",\n () => ignorePlayingUpdates(() => playing.value = true),\n listenerOptions\n );\n useEventListener(\n target,\n \"enterpictureinpicture\",\n () => isPictureInPicture.value = true,\n listenerOptions\n );\n useEventListener(\n target,\n \"leavepictureinpicture\",\n () => isPictureInPicture.value = false,\n listenerOptions\n );\n useEventListener(\n target,\n \"volumechange\",\n () => {\n const el = toValue(target);\n if (!el)\n return;\n volume.value = el.volume;\n muted.value = el.muted;\n },\n listenerOptions\n );\n const listeners = [];\n const stop = watch([target], () => {\n const el = toValue(target);\n if (!el)\n return;\n stop();\n listeners[0] = useEventListener(el.textTracks, \"addtrack\", () => tracks.value = tracksToArray(el.textTracks), listenerOptions);\n listeners[1] = useEventListener(el.textTracks, \"removetrack\", () => tracks.value = tracksToArray(el.textTracks), listenerOptions);\n listeners[2] = useEventListener(el.textTracks, \"change\", () => tracks.value = tracksToArray(el.textTracks), listenerOptions);\n });\n tryOnScopeDispose(() => listeners.forEach((listener) => listener()));\n return {\n currentTime,\n duration,\n waiting,\n seeking,\n ended,\n stalled,\n buffered,\n playing,\n rate,\n // Volume\n volume,\n muted,\n // Tracks\n tracks,\n selectedTrack,\n enableTrack,\n disableTrack,\n // Picture in Picture\n supportsPictureInPicture,\n togglePictureInPicture,\n isPictureInPicture,\n // Events\n onSourceError: sourceErrorEvent.on,\n onPlaybackError: playbackErrorEvent.on\n };\n}\n\nfunction useMemoize(resolver, options) {\n const initCache = () => {\n if (options == null ? void 0 : options.cache)\n return shallowReactive(options.cache);\n return shallowReactive(/* @__PURE__ */ new Map());\n };\n const cache = initCache();\n const generateKey = (...args) => (options == null ? void 0 : options.getKey) ? options.getKey(...args) : JSON.stringify(args);\n const _loadData = (key, ...args) => {\n cache.set(key, resolver(...args));\n return cache.get(key);\n };\n const loadData = (...args) => _loadData(generateKey(...args), ...args);\n const deleteData = (...args) => {\n cache.delete(generateKey(...args));\n };\n const clearData = () => {\n cache.clear();\n };\n const memoized = (...args) => {\n const key = generateKey(...args);\n if (cache.has(key))\n return cache.get(key);\n return _loadData(key, ...args);\n };\n memoized.load = loadData;\n memoized.delete = deleteData;\n memoized.clear = clearData;\n memoized.generateKey = generateKey;\n memoized.cache = cache;\n return memoized;\n}\n\nfunction useMemory(options = {}) {\n const memory = ref();\n const isSupported = useSupported(() => typeof performance !== \"undefined\" && \"memory\" in performance);\n if (isSupported.value) {\n const { interval = 1e3 } = options;\n useIntervalFn(() => {\n memory.value = performance.memory;\n }, interval, { immediate: options.immediate, immediateCallback: options.immediateCallback });\n }\n return { isSupported, memory };\n}\n\nconst UseMouseBuiltinExtractors = {\n page: (event) => [event.pageX, event.pageY],\n client: (event) => [event.clientX, event.clientY],\n screen: (event) => [event.screenX, event.screenY],\n movement: (event) => event instanceof MouseEvent ? [event.movementX, event.movementY] : null\n};\nfunction useMouse(options = {}) {\n const {\n type = \"page\",\n touch = true,\n resetOnTouchEnds = false,\n initialValue = { x: 0, y: 0 },\n window = defaultWindow,\n target = window,\n scroll = true,\n eventFilter\n } = options;\n let _prevMouseEvent = null;\n let _prevScrollX = 0;\n let _prevScrollY = 0;\n const x = shallowRef(initialValue.x);\n const y = shallowRef(initialValue.y);\n const sourceType = shallowRef(null);\n const extractor = typeof type === \"function\" ? type : UseMouseBuiltinExtractors[type];\n const mouseHandler = (event) => {\n const result = extractor(event);\n _prevMouseEvent = event;\n if (result) {\n [x.value, y.value] = result;\n sourceType.value = \"mouse\";\n }\n if (window) {\n _prevScrollX = window.scrollX;\n _prevScrollY = window.scrollY;\n }\n };\n const touchHandler = (event) => {\n if (event.touches.length > 0) {\n const result = extractor(event.touches[0]);\n if (result) {\n [x.value, y.value] = result;\n sourceType.value = \"touch\";\n }\n }\n };\n const scrollHandler = () => {\n if (!_prevMouseEvent || !window)\n return;\n const pos = extractor(_prevMouseEvent);\n if (_prevMouseEvent instanceof MouseEvent && pos) {\n x.value = pos[0] + window.scrollX - _prevScrollX;\n y.value = pos[1] + window.scrollY - _prevScrollY;\n }\n };\n const reset = () => {\n x.value = initialValue.x;\n y.value = initialValue.y;\n };\n const mouseHandlerWrapper = eventFilter ? (event) => eventFilter(() => mouseHandler(event), {}) : (event) => mouseHandler(event);\n const touchHandlerWrapper = eventFilter ? (event) => eventFilter(() => touchHandler(event), {}) : (event) => touchHandler(event);\n const scrollHandlerWrapper = eventFilter ? () => eventFilter(() => scrollHandler(), {}) : () => scrollHandler();\n if (target) {\n const listenerOptions = { passive: true };\n useEventListener(target, [\"mousemove\", \"dragover\"], mouseHandlerWrapper, listenerOptions);\n if (touch && type !== \"movement\") {\n useEventListener(target, [\"touchstart\", \"touchmove\"], touchHandlerWrapper, listenerOptions);\n if (resetOnTouchEnds)\n useEventListener(target, \"touchend\", reset, listenerOptions);\n }\n if (scroll && type === \"page\")\n useEventListener(window, \"scroll\", scrollHandlerWrapper, listenerOptions);\n }\n return {\n x,\n y,\n sourceType\n };\n}\n\nfunction useMouseInElement(target, options = {}) {\n const {\n handleOutside = true,\n window = defaultWindow\n } = options;\n const type = options.type || \"page\";\n const { x, y, sourceType } = useMouse(options);\n const targetRef = shallowRef(target != null ? target : window == null ? void 0 : window.document.body);\n const elementX = shallowRef(0);\n const elementY = shallowRef(0);\n const elementPositionX = shallowRef(0);\n const elementPositionY = shallowRef(0);\n const elementHeight = shallowRef(0);\n const elementWidth = shallowRef(0);\n const isOutside = shallowRef(true);\n let stop = () => {\n };\n if (window) {\n stop = watch(\n [targetRef, x, y],\n () => {\n const el = unrefElement(targetRef);\n if (!el || !(el instanceof Element))\n return;\n const {\n left,\n top,\n width,\n height\n } = el.getBoundingClientRect();\n elementPositionX.value = left + (type === \"page\" ? window.pageXOffset : 0);\n elementPositionY.value = top + (type === \"page\" ? window.pageYOffset : 0);\n elementHeight.value = height;\n elementWidth.value = width;\n const elX = x.value - elementPositionX.value;\n const elY = y.value - elementPositionY.value;\n isOutside.value = width === 0 || height === 0 || elX < 0 || elY < 0 || elX > width || elY > height;\n if (handleOutside || !isOutside.value) {\n elementX.value = elX;\n elementY.value = elY;\n }\n },\n { immediate: true }\n );\n useEventListener(\n document,\n \"mouseleave\",\n () => isOutside.value = true,\n { passive: true }\n );\n }\n return {\n x,\n y,\n sourceType,\n elementX,\n elementY,\n elementPositionX,\n elementPositionY,\n elementHeight,\n elementWidth,\n isOutside,\n stop\n };\n}\n\nfunction useMousePressed(options = {}) {\n const {\n touch = true,\n drag = true,\n capture = false,\n initialValue = false,\n window = defaultWindow\n } = options;\n const pressed = shallowRef(initialValue);\n const sourceType = shallowRef(null);\n if (!window) {\n return {\n pressed,\n sourceType\n };\n }\n const onPressed = (srcType) => (event) => {\n var _a;\n pressed.value = true;\n sourceType.value = srcType;\n (_a = options.onPressed) == null ? void 0 : _a.call(options, event);\n };\n const onReleased = (event) => {\n var _a;\n pressed.value = false;\n sourceType.value = null;\n (_a = options.onReleased) == null ? void 0 : _a.call(options, event);\n };\n const target = computed(() => unrefElement(options.target) || window);\n const listenerOptions = { passive: true, capture };\n useEventListener(target, \"mousedown\", onPressed(\"mouse\"), listenerOptions);\n useEventListener(window, \"mouseleave\", onReleased, listenerOptions);\n useEventListener(window, \"mouseup\", onReleased, listenerOptions);\n if (drag) {\n useEventListener(target, \"dragstart\", onPressed(\"mouse\"), listenerOptions);\n useEventListener(window, \"drop\", onReleased, listenerOptions);\n useEventListener(window, \"dragend\", onReleased, listenerOptions);\n }\n if (touch) {\n useEventListener(target, \"touchstart\", onPressed(\"touch\"), listenerOptions);\n useEventListener(window, \"touchend\", onReleased, listenerOptions);\n useEventListener(window, \"touchcancel\", onReleased, listenerOptions);\n }\n return {\n pressed,\n sourceType\n };\n}\n\nfunction useNavigatorLanguage(options = {}) {\n const { window = defaultWindow } = options;\n const navigator = window == null ? void 0 : window.navigator;\n const isSupported = useSupported(() => navigator && \"language\" in navigator);\n const language = shallowRef(navigator == null ? void 0 : navigator.language);\n useEventListener(window, \"languagechange\", () => {\n if (navigator)\n language.value = navigator.language;\n }, { passive: true });\n return {\n isSupported,\n language\n };\n}\n\nfunction useNetwork(options = {}) {\n const { window = defaultWindow } = options;\n const navigator = window == null ? void 0 : window.navigator;\n const isSupported = useSupported(() => navigator && \"connection\" in navigator);\n const isOnline = shallowRef(true);\n const saveData = shallowRef(false);\n const offlineAt = shallowRef(void 0);\n const onlineAt = shallowRef(void 0);\n const downlink = shallowRef(void 0);\n const downlinkMax = shallowRef(void 0);\n const rtt = shallowRef(void 0);\n const effectiveType = shallowRef(void 0);\n const type = shallowRef(\"unknown\");\n const connection = isSupported.value && navigator.connection;\n function updateNetworkInformation() {\n if (!navigator)\n return;\n isOnline.value = navigator.onLine;\n offlineAt.value = isOnline.value ? void 0 : Date.now();\n onlineAt.value = isOnline.value ? Date.now() : void 0;\n if (connection) {\n downlink.value = connection.downlink;\n downlinkMax.value = connection.downlinkMax;\n effectiveType.value = connection.effectiveType;\n rtt.value = connection.rtt;\n saveData.value = connection.saveData;\n type.value = connection.type;\n }\n }\n const listenerOptions = { passive: true };\n if (window) {\n useEventListener(window, \"offline\", () => {\n isOnline.value = false;\n offlineAt.value = Date.now();\n }, listenerOptions);\n useEventListener(window, \"online\", () => {\n isOnline.value = true;\n onlineAt.value = Date.now();\n }, listenerOptions);\n }\n if (connection)\n useEventListener(connection, \"change\", updateNetworkInformation, listenerOptions);\n updateNetworkInformation();\n return {\n isSupported,\n isOnline: readonly(isOnline),\n saveData: readonly(saveData),\n offlineAt: readonly(offlineAt),\n onlineAt: readonly(onlineAt),\n downlink: readonly(downlink),\n downlinkMax: readonly(downlinkMax),\n effectiveType: readonly(effectiveType),\n rtt: readonly(rtt),\n type: readonly(type)\n };\n}\n\nfunction useNow(options = {}) {\n const {\n controls: exposeControls = false,\n interval = \"requestAnimationFrame\"\n } = options;\n const now = ref(/* @__PURE__ */ new Date());\n const update = () => now.value = /* @__PURE__ */ new Date();\n const controls = interval === \"requestAnimationFrame\" ? useRafFn(update, { immediate: true }) : useIntervalFn(update, interval, { immediate: true });\n if (exposeControls) {\n return {\n now,\n ...controls\n };\n } else {\n return now;\n }\n}\n\nfunction useObjectUrl(object) {\n const url = shallowRef();\n const release = () => {\n if (url.value)\n URL.revokeObjectURL(url.value);\n url.value = void 0;\n };\n watch(\n () => toValue(object),\n (newObject) => {\n release();\n if (newObject)\n url.value = URL.createObjectURL(newObject);\n },\n { immediate: true }\n );\n tryOnScopeDispose(release);\n return readonly(url);\n}\n\nfunction useClamp(value, min, max) {\n if (typeof value === \"function\" || isReadonly(value))\n return computed(() => clamp(toValue(value), toValue(min), toValue(max)));\n const _value = ref(value);\n return computed({\n get() {\n return _value.value = clamp(_value.value, toValue(min), toValue(max));\n },\n set(value2) {\n _value.value = clamp(value2, toValue(min), toValue(max));\n }\n });\n}\n\nfunction useOffsetPagination(options) {\n const {\n total = Number.POSITIVE_INFINITY,\n pageSize = 10,\n page = 1,\n onPageChange = noop,\n onPageSizeChange = noop,\n onPageCountChange = noop\n } = options;\n const currentPageSize = useClamp(pageSize, 1, Number.POSITIVE_INFINITY);\n const pageCount = computed(() => Math.max(\n 1,\n Math.ceil(toValue(total) / toValue(currentPageSize))\n ));\n const currentPage = useClamp(page, 1, pageCount);\n const isFirstPage = computed(() => currentPage.value === 1);\n const isLastPage = computed(() => currentPage.value === pageCount.value);\n if (isRef(page)) {\n syncRef(page, currentPage, {\n direction: isReadonly(page) ? \"ltr\" : \"both\"\n });\n }\n if (isRef(pageSize)) {\n syncRef(pageSize, currentPageSize, {\n direction: isReadonly(pageSize) ? \"ltr\" : \"both\"\n });\n }\n function prev() {\n currentPage.value--;\n }\n function next() {\n currentPage.value++;\n }\n const returnValue = {\n currentPage,\n currentPageSize,\n pageCount,\n isFirstPage,\n isLastPage,\n prev,\n next\n };\n watch(currentPage, () => {\n onPageChange(reactive(returnValue));\n });\n watch(currentPageSize, () => {\n onPageSizeChange(reactive(returnValue));\n });\n watch(pageCount, () => {\n onPageCountChange(reactive(returnValue));\n });\n return returnValue;\n}\n\nfunction useOnline(options = {}) {\n const { isOnline } = useNetwork(options);\n return isOnline;\n}\n\nfunction usePageLeave(options = {}) {\n const { window = defaultWindow } = options;\n const isLeft = shallowRef(false);\n const handler = (event) => {\n if (!window)\n return;\n event = event || window.event;\n const from = event.relatedTarget || event.toElement;\n isLeft.value = !from;\n };\n if (window) {\n const listenerOptions = { passive: true };\n useEventListener(window, \"mouseout\", handler, listenerOptions);\n useEventListener(window.document, \"mouseleave\", handler, listenerOptions);\n useEventListener(window.document, \"mouseenter\", handler, listenerOptions);\n }\n return isLeft;\n}\n\nfunction useScreenOrientation(options = {}) {\n const {\n window = defaultWindow\n } = options;\n const isSupported = useSupported(() => window && \"screen\" in window && \"orientation\" in window.screen);\n const screenOrientation = isSupported.value ? window.screen.orientation : {};\n const orientation = ref(screenOrientation.type);\n const angle = shallowRef(screenOrientation.angle || 0);\n if (isSupported.value) {\n useEventListener(window, \"orientationchange\", () => {\n orientation.value = screenOrientation.type;\n angle.value = screenOrientation.angle;\n }, { passive: true });\n }\n const lockOrientation = (type) => {\n if (isSupported.value && typeof screenOrientation.lock === \"function\")\n return screenOrientation.lock(type);\n return Promise.reject(new Error(\"Not supported\"));\n };\n const unlockOrientation = () => {\n if (isSupported.value && typeof screenOrientation.unlock === \"function\")\n screenOrientation.unlock();\n };\n return {\n isSupported,\n orientation,\n angle,\n lockOrientation,\n unlockOrientation\n };\n}\n\nfunction useParallax(target, options = {}) {\n const {\n deviceOrientationTiltAdjust = (i) => i,\n deviceOrientationRollAdjust = (i) => i,\n mouseTiltAdjust = (i) => i,\n mouseRollAdjust = (i) => i,\n window = defaultWindow\n } = options;\n const orientation = reactive(useDeviceOrientation({ window }));\n const screenOrientation = reactive(useScreenOrientation({ window }));\n const {\n elementX: x,\n elementY: y,\n elementWidth: width,\n elementHeight: height\n } = useMouseInElement(target, { handleOutside: false, window });\n const source = computed(() => {\n if (orientation.isSupported && (orientation.alpha != null && orientation.alpha !== 0 || orientation.gamma != null && orientation.gamma !== 0)) {\n return \"deviceOrientation\";\n }\n return \"mouse\";\n });\n const roll = computed(() => {\n if (source.value === \"deviceOrientation\") {\n let value;\n switch (screenOrientation.orientation) {\n case \"landscape-primary\":\n value = orientation.gamma / 90;\n break;\n case \"landscape-secondary\":\n value = -orientation.gamma / 90;\n break;\n case \"portrait-primary\":\n value = -orientation.beta / 90;\n break;\n case \"portrait-secondary\":\n value = orientation.beta / 90;\n break;\n default:\n value = -orientation.beta / 90;\n }\n return deviceOrientationRollAdjust(value);\n } else {\n const value = -(y.value - height.value / 2) / height.value;\n return mouseRollAdjust(value);\n }\n });\n const tilt = computed(() => {\n if (source.value === \"deviceOrientation\") {\n let value;\n switch (screenOrientation.orientation) {\n case \"landscape-primary\":\n value = orientation.beta / 90;\n break;\n case \"landscape-secondary\":\n value = -orientation.beta / 90;\n break;\n case \"portrait-primary\":\n value = orientation.gamma / 90;\n break;\n case \"portrait-secondary\":\n value = -orientation.gamma / 90;\n break;\n default:\n value = orientation.gamma / 90;\n }\n return deviceOrientationTiltAdjust(value);\n } else {\n const value = (x.value - width.value / 2) / width.value;\n return mouseTiltAdjust(value);\n }\n });\n return { roll, tilt, source };\n}\n\nfunction useParentElement(element = useCurrentElement()) {\n const parentElement = shallowRef();\n const update = () => {\n const el = unrefElement(element);\n if (el)\n parentElement.value = el.parentElement;\n };\n tryOnMounted(update);\n watch(() => toValue(element), update);\n return parentElement;\n}\n\nfunction usePerformanceObserver(options, callback) {\n const {\n window = defaultWindow,\n immediate = true,\n ...performanceOptions\n } = options;\n const isSupported = useSupported(() => window && \"PerformanceObserver\" in window);\n let observer;\n const stop = () => {\n observer == null ? void 0 : observer.disconnect();\n };\n const start = () => {\n if (isSupported.value) {\n stop();\n observer = new PerformanceObserver(callback);\n observer.observe(performanceOptions);\n }\n };\n tryOnScopeDispose(stop);\n if (immediate)\n start();\n return {\n isSupported,\n start,\n stop\n };\n}\n\nconst defaultState = {\n x: 0,\n y: 0,\n pointerId: 0,\n pressure: 0,\n tiltX: 0,\n tiltY: 0,\n width: 0,\n height: 0,\n twist: 0,\n pointerType: null\n};\nconst keys = /* @__PURE__ */ Object.keys(defaultState);\nfunction usePointer(options = {}) {\n const {\n target = defaultWindow\n } = options;\n const isInside = shallowRef(false);\n const state = ref(options.initialValue || {});\n Object.assign(state.value, defaultState, state.value);\n const handler = (event) => {\n isInside.value = true;\n if (options.pointerTypes && !options.pointerTypes.includes(event.pointerType))\n return;\n state.value = objectPick(event, keys, false);\n };\n if (target) {\n const listenerOptions = { passive: true };\n useEventListener(target, [\"pointerdown\", \"pointermove\", \"pointerup\"], handler, listenerOptions);\n useEventListener(target, \"pointerleave\", () => isInside.value = false, listenerOptions);\n }\n return {\n ...toRefs(state),\n isInside\n };\n}\n\nfunction usePointerLock(target, options = {}) {\n const { document = defaultDocument } = options;\n const isSupported = useSupported(() => document && \"pointerLockElement\" in document);\n const element = shallowRef();\n const triggerElement = shallowRef();\n let targetElement;\n if (isSupported.value) {\n const listenerOptions = { passive: true };\n useEventListener(document, \"pointerlockchange\", () => {\n var _a;\n const currentElement = (_a = document.pointerLockElement) != null ? _a : element.value;\n if (targetElement && currentElement === targetElement) {\n element.value = document.pointerLockElement;\n if (!element.value)\n targetElement = triggerElement.value = null;\n }\n }, listenerOptions);\n useEventListener(document, \"pointerlockerror\", () => {\n var _a;\n const currentElement = (_a = document.pointerLockElement) != null ? _a : element.value;\n if (targetElement && currentElement === targetElement) {\n const action = document.pointerLockElement ? \"release\" : \"acquire\";\n throw new Error(`Failed to ${action} pointer lock.`);\n }\n }, listenerOptions);\n }\n async function lock(e) {\n var _a;\n if (!isSupported.value)\n throw new Error(\"Pointer Lock API is not supported by your browser.\");\n triggerElement.value = e instanceof Event ? e.currentTarget : null;\n targetElement = e instanceof Event ? (_a = unrefElement(target)) != null ? _a : triggerElement.value : unrefElement(e);\n if (!targetElement)\n throw new Error(\"Target element undefined.\");\n targetElement.requestPointerLock();\n return await until(element).toBe(targetElement);\n }\n async function unlock() {\n if (!element.value)\n return false;\n document.exitPointerLock();\n await until(element).toBeNull();\n return true;\n }\n return {\n isSupported,\n element,\n triggerElement,\n lock,\n unlock\n };\n}\n\nfunction usePointerSwipe(target, options = {}) {\n const targetRef = toRef(target);\n const {\n threshold = 50,\n onSwipe,\n onSwipeEnd,\n onSwipeStart,\n disableTextSelect = false\n } = options;\n const posStart = reactive({ x: 0, y: 0 });\n const updatePosStart = (x, y) => {\n posStart.x = x;\n posStart.y = y;\n };\n const posEnd = reactive({ x: 0, y: 0 });\n const updatePosEnd = (x, y) => {\n posEnd.x = x;\n posEnd.y = y;\n };\n const distanceX = computed(() => posStart.x - posEnd.x);\n const distanceY = computed(() => posStart.y - posEnd.y);\n const { max, abs } = Math;\n const isThresholdExceeded = computed(() => max(abs(distanceX.value), abs(distanceY.value)) >= threshold);\n const isSwiping = shallowRef(false);\n const isPointerDown = shallowRef(false);\n const direction = computed(() => {\n if (!isThresholdExceeded.value)\n return \"none\";\n if (abs(distanceX.value) > abs(distanceY.value)) {\n return distanceX.value > 0 ? \"left\" : \"right\";\n } else {\n return distanceY.value > 0 ? \"up\" : \"down\";\n }\n });\n const eventIsAllowed = (e) => {\n var _a, _b, _c;\n const isReleasingButton = e.buttons === 0;\n const isPrimaryButton = e.buttons === 1;\n return (_c = (_b = (_a = options.pointerTypes) == null ? void 0 : _a.includes(e.pointerType)) != null ? _b : isReleasingButton || isPrimaryButton) != null ? _c : true;\n };\n const listenerOptions = { passive: true };\n const stops = [\n useEventListener(target, \"pointerdown\", (e) => {\n if (!eventIsAllowed(e))\n return;\n isPointerDown.value = true;\n const eventTarget = e.target;\n eventTarget == null ? void 0 : eventTarget.setPointerCapture(e.pointerId);\n const { clientX: x, clientY: y } = e;\n updatePosStart(x, y);\n updatePosEnd(x, y);\n onSwipeStart == null ? void 0 : onSwipeStart(e);\n }, listenerOptions),\n useEventListener(target, \"pointermove\", (e) => {\n if (!eventIsAllowed(e))\n return;\n if (!isPointerDown.value)\n return;\n const { clientX: x, clientY: y } = e;\n updatePosEnd(x, y);\n if (!isSwiping.value && isThresholdExceeded.value)\n isSwiping.value = true;\n if (isSwiping.value)\n onSwipe == null ? void 0 : onSwipe(e);\n }, listenerOptions),\n useEventListener(target, \"pointerup\", (e) => {\n if (!eventIsAllowed(e))\n return;\n if (isSwiping.value)\n onSwipeEnd == null ? void 0 : onSwipeEnd(e, direction.value);\n isPointerDown.value = false;\n isSwiping.value = false;\n }, listenerOptions)\n ];\n tryOnMounted(() => {\n var _a, _b, _c, _d, _e, _f, _g, _h;\n (_b = (_a = targetRef.value) == null ? void 0 : _a.style) == null ? void 0 : _b.setProperty(\"touch-action\", \"none\");\n if (disableTextSelect) {\n (_d = (_c = targetRef.value) == null ? void 0 : _c.style) == null ? void 0 : _d.setProperty(\"-webkit-user-select\", \"none\");\n (_f = (_e = targetRef.value) == null ? void 0 : _e.style) == null ? void 0 : _f.setProperty(\"-ms-user-select\", \"none\");\n (_h = (_g = targetRef.value) == null ? void 0 : _g.style) == null ? void 0 : _h.setProperty(\"user-select\", \"none\");\n }\n });\n const stop = () => stops.forEach((s) => s());\n return {\n isSwiping: readonly(isSwiping),\n direction: readonly(direction),\n posStart: readonly(posStart),\n posEnd: readonly(posEnd),\n distanceX,\n distanceY,\n stop\n };\n}\n\nfunction usePreferredColorScheme(options) {\n const isLight = useMediaQuery(\"(prefers-color-scheme: light)\", options);\n const isDark = useMediaQuery(\"(prefers-color-scheme: dark)\", options);\n return computed(() => {\n if (isDark.value)\n return \"dark\";\n if (isLight.value)\n return \"light\";\n return \"no-preference\";\n });\n}\n\nfunction usePreferredContrast(options) {\n const isMore = useMediaQuery(\"(prefers-contrast: more)\", options);\n const isLess = useMediaQuery(\"(prefers-contrast: less)\", options);\n const isCustom = useMediaQuery(\"(prefers-contrast: custom)\", options);\n return computed(() => {\n if (isMore.value)\n return \"more\";\n if (isLess.value)\n return \"less\";\n if (isCustom.value)\n return \"custom\";\n return \"no-preference\";\n });\n}\n\nfunction usePreferredLanguages(options = {}) {\n const { window = defaultWindow } = options;\n if (!window)\n return ref([\"en\"]);\n const navigator = window.navigator;\n const value = ref(navigator.languages);\n useEventListener(window, \"languagechange\", () => {\n value.value = navigator.languages;\n }, { passive: true });\n return value;\n}\n\nfunction usePreferredReducedMotion(options) {\n const isReduced = useMediaQuery(\"(prefers-reduced-motion: reduce)\", options);\n return computed(() => {\n if (isReduced.value)\n return \"reduce\";\n return \"no-preference\";\n });\n}\n\nfunction usePreferredReducedTransparency(options) {\n const isReduced = useMediaQuery(\"(prefers-reduced-transparency: reduce)\", options);\n return computed(() => {\n if (isReduced.value)\n return \"reduce\";\n return \"no-preference\";\n });\n}\n\nfunction usePrevious(value, initialValue) {\n const previous = shallowRef(initialValue);\n watch(\n toRef(value),\n (_, oldValue) => {\n previous.value = oldValue;\n },\n { flush: \"sync\" }\n );\n return readonly(previous);\n}\n\nconst topVarName = \"--vueuse-safe-area-top\";\nconst rightVarName = \"--vueuse-safe-area-right\";\nconst bottomVarName = \"--vueuse-safe-area-bottom\";\nconst leftVarName = \"--vueuse-safe-area-left\";\nfunction useScreenSafeArea() {\n const top = shallowRef(\"\");\n const right = shallowRef(\"\");\n const bottom = shallowRef(\"\");\n const left = shallowRef(\"\");\n if (isClient) {\n const topCssVar = useCssVar(topVarName);\n const rightCssVar = useCssVar(rightVarName);\n const bottomCssVar = useCssVar(bottomVarName);\n const leftCssVar = useCssVar(leftVarName);\n topCssVar.value = \"env(safe-area-inset-top, 0px)\";\n rightCssVar.value = \"env(safe-area-inset-right, 0px)\";\n bottomCssVar.value = \"env(safe-area-inset-bottom, 0px)\";\n leftCssVar.value = \"env(safe-area-inset-left, 0px)\";\n update();\n useEventListener(\"resize\", useDebounceFn(update), { passive: true });\n }\n function update() {\n top.value = getValue(topVarName);\n right.value = getValue(rightVarName);\n bottom.value = getValue(bottomVarName);\n left.value = getValue(leftVarName);\n }\n return {\n top,\n right,\n bottom,\n left,\n update\n };\n}\nfunction getValue(position) {\n return getComputedStyle(document.documentElement).getPropertyValue(position);\n}\n\nfunction useScriptTag(src, onLoaded = noop, options = {}) {\n const {\n immediate = true,\n manual = false,\n type = \"text/javascript\",\n async = true,\n crossOrigin,\n referrerPolicy,\n noModule,\n defer,\n document = defaultDocument,\n attrs = {}\n } = options;\n const scriptTag = shallowRef(null);\n let _promise = null;\n const loadScript = (waitForScriptLoad) => new Promise((resolve, reject) => {\n const resolveWithElement = (el2) => {\n scriptTag.value = el2;\n resolve(el2);\n return el2;\n };\n if (!document) {\n resolve(false);\n return;\n }\n let shouldAppend = false;\n let el = document.querySelector(`script[src=\"${toValue(src)}\"]`);\n if (!el) {\n el = document.createElement(\"script\");\n el.type = type;\n el.async = async;\n el.src = toValue(src);\n if (defer)\n el.defer = defer;\n if (crossOrigin)\n el.crossOrigin = crossOrigin;\n if (noModule)\n el.noModule = noModule;\n if (referrerPolicy)\n el.referrerPolicy = referrerPolicy;\n Object.entries(attrs).forEach(([name, value]) => el == null ? void 0 : el.setAttribute(name, value));\n shouldAppend = true;\n } else if (el.hasAttribute(\"data-loaded\")) {\n resolveWithElement(el);\n }\n const listenerOptions = {\n passive: true\n };\n useEventListener(el, \"error\", (event) => reject(event), listenerOptions);\n useEventListener(el, \"abort\", (event) => reject(event), listenerOptions);\n useEventListener(el, \"load\", () => {\n el.setAttribute(\"data-loaded\", \"true\");\n onLoaded(el);\n resolveWithElement(el);\n }, listenerOptions);\n if (shouldAppend)\n el = document.head.appendChild(el);\n if (!waitForScriptLoad)\n resolveWithElement(el);\n });\n const load = (waitForScriptLoad = true) => {\n if (!_promise)\n _promise = loadScript(waitForScriptLoad);\n return _promise;\n };\n const unload = () => {\n if (!document)\n return;\n _promise = null;\n if (scriptTag.value)\n scriptTag.value = null;\n const el = document.querySelector(`script[src=\"${toValue(src)}\"]`);\n if (el)\n document.head.removeChild(el);\n };\n if (immediate && !manual)\n tryOnMounted(load);\n if (!manual)\n tryOnUnmounted(unload);\n return { scriptTag, load, unload };\n}\n\nfunction checkOverflowScroll(ele) {\n const style = window.getComputedStyle(ele);\n if (style.overflowX === \"scroll\" || style.overflowY === \"scroll\" || style.overflowX === \"auto\" && ele.clientWidth < ele.scrollWidth || style.overflowY === \"auto\" && ele.clientHeight < ele.scrollHeight) {\n return true;\n } else {\n const parent = ele.parentNode;\n if (!parent || parent.tagName === \"BODY\")\n return false;\n return checkOverflowScroll(parent);\n }\n}\nfunction preventDefault(rawEvent) {\n const e = rawEvent || window.event;\n const _target = e.target;\n if (checkOverflowScroll(_target))\n return false;\n if (e.touches.length > 1)\n return true;\n if (e.preventDefault)\n e.preventDefault();\n return false;\n}\nconst elInitialOverflow = /* @__PURE__ */ new WeakMap();\nfunction useScrollLock(element, initialState = false) {\n const isLocked = shallowRef(initialState);\n let stopTouchMoveListener = null;\n let initialOverflow = \"\";\n watch(toRef(element), (el) => {\n const target = resolveElement(toValue(el));\n if (target) {\n const ele = target;\n if (!elInitialOverflow.get(ele))\n elInitialOverflow.set(ele, ele.style.overflow);\n if (ele.style.overflow !== \"hidden\")\n initialOverflow = ele.style.overflow;\n if (ele.style.overflow === \"hidden\")\n return isLocked.value = true;\n if (isLocked.value)\n return ele.style.overflow = \"hidden\";\n }\n }, {\n immediate: true\n });\n const lock = () => {\n const el = resolveElement(toValue(element));\n if (!el || isLocked.value)\n return;\n if (isIOS) {\n stopTouchMoveListener = useEventListener(\n el,\n \"touchmove\",\n (e) => {\n preventDefault(e);\n },\n { passive: false }\n );\n }\n el.style.overflow = \"hidden\";\n isLocked.value = true;\n };\n const unlock = () => {\n const el = resolveElement(toValue(element));\n if (!el || !isLocked.value)\n return;\n if (isIOS)\n stopTouchMoveListener == null ? void 0 : stopTouchMoveListener();\n el.style.overflow = initialOverflow;\n elInitialOverflow.delete(el);\n isLocked.value = false;\n };\n tryOnScopeDispose(unlock);\n return computed({\n get() {\n return isLocked.value;\n },\n set(v) {\n if (v)\n lock();\n else unlock();\n }\n });\n}\n\nfunction useSessionStorage(key, initialValue, options = {}) {\n const { window = defaultWindow } = options;\n return useStorage(key, initialValue, window == null ? void 0 : window.sessionStorage, options);\n}\n\nfunction useShare(shareOptions = {}, options = {}) {\n const { navigator = defaultNavigator } = options;\n const _navigator = navigator;\n const isSupported = useSupported(() => _navigator && \"canShare\" in _navigator);\n const share = async (overrideOptions = {}) => {\n if (isSupported.value) {\n const data = {\n ...toValue(shareOptions),\n ...toValue(overrideOptions)\n };\n let granted = true;\n if (data.files && _navigator.canShare)\n granted = _navigator.canShare({ files: data.files });\n if (granted)\n return _navigator.share(data);\n }\n };\n return {\n isSupported,\n share\n };\n}\n\nconst defaultSortFn = (source, compareFn) => source.sort(compareFn);\nconst defaultCompare = (a, b) => a - b;\nfunction useSorted(...args) {\n var _a, _b, _c, _d;\n const [source] = args;\n let compareFn = defaultCompare;\n let options = {};\n if (args.length === 2) {\n if (typeof args[1] === \"object\") {\n options = args[1];\n compareFn = (_a = options.compareFn) != null ? _a : defaultCompare;\n } else {\n compareFn = (_b = args[1]) != null ? _b : defaultCompare;\n }\n } else if (args.length > 2) {\n compareFn = (_c = args[1]) != null ? _c : defaultCompare;\n options = (_d = args[2]) != null ? _d : {};\n }\n const {\n dirty = false,\n sortFn = defaultSortFn\n } = options;\n if (!dirty)\n return computed(() => sortFn([...toValue(source)], compareFn));\n watchEffect(() => {\n const result = sortFn(toValue(source), compareFn);\n if (isRef(source))\n source.value = result;\n else\n source.splice(0, source.length, ...result);\n });\n return source;\n}\n\nfunction useSpeechRecognition(options = {}) {\n const {\n interimResults = true,\n continuous = true,\n maxAlternatives = 1,\n window = defaultWindow\n } = options;\n const lang = toRef(options.lang || \"en-US\");\n const isListening = shallowRef(false);\n const isFinal = shallowRef(false);\n const result = shallowRef(\"\");\n const error = shallowRef(void 0);\n let recognition;\n const start = () => {\n isListening.value = true;\n };\n const stop = () => {\n isListening.value = false;\n };\n const toggle = (value = !isListening.value) => {\n if (value) {\n start();\n } else {\n stop();\n }\n };\n const SpeechRecognition = window && (window.SpeechRecognition || window.webkitSpeechRecognition);\n const isSupported = useSupported(() => SpeechRecognition);\n if (isSupported.value) {\n recognition = new SpeechRecognition();\n recognition.continuous = continuous;\n recognition.interimResults = interimResults;\n recognition.lang = toValue(lang);\n recognition.maxAlternatives = maxAlternatives;\n recognition.onstart = () => {\n isListening.value = true;\n isFinal.value = false;\n };\n watch(lang, (lang2) => {\n if (recognition && !isListening.value)\n recognition.lang = lang2;\n });\n recognition.onresult = (event) => {\n const currentResult = event.results[event.resultIndex];\n const { transcript } = currentResult[0];\n isFinal.value = currentResult.isFinal;\n result.value = transcript;\n error.value = void 0;\n };\n recognition.onerror = (event) => {\n error.value = event;\n };\n recognition.onend = () => {\n isListening.value = false;\n recognition.lang = toValue(lang);\n };\n watch(isListening, (newValue, oldValue) => {\n if (newValue === oldValue)\n return;\n if (newValue)\n recognition.start();\n else\n recognition.stop();\n });\n }\n tryOnScopeDispose(() => {\n stop();\n });\n return {\n isSupported,\n isListening,\n isFinal,\n recognition,\n result,\n error,\n toggle,\n start,\n stop\n };\n}\n\nfunction useSpeechSynthesis(text, options = {}) {\n const {\n pitch = 1,\n rate = 1,\n volume = 1,\n window = defaultWindow\n } = options;\n const synth = window && window.speechSynthesis;\n const isSupported = useSupported(() => synth);\n const isPlaying = shallowRef(false);\n const status = shallowRef(\"init\");\n const spokenText = toRef(text || \"\");\n const lang = toRef(options.lang || \"en-US\");\n const error = shallowRef(void 0);\n const toggle = (value = !isPlaying.value) => {\n isPlaying.value = value;\n };\n const bindEventsForUtterance = (utterance2) => {\n utterance2.lang = toValue(lang);\n utterance2.voice = toValue(options.voice) || null;\n utterance2.pitch = toValue(pitch);\n utterance2.rate = toValue(rate);\n utterance2.volume = volume;\n utterance2.onstart = () => {\n isPlaying.value = true;\n status.value = \"play\";\n };\n utterance2.onpause = () => {\n isPlaying.value = false;\n status.value = \"pause\";\n };\n utterance2.onresume = () => {\n isPlaying.value = true;\n status.value = \"play\";\n };\n utterance2.onend = () => {\n isPlaying.value = false;\n status.value = \"end\";\n };\n utterance2.onerror = (event) => {\n error.value = event;\n };\n };\n const utterance = computed(() => {\n isPlaying.value = false;\n status.value = \"init\";\n const newUtterance = new SpeechSynthesisUtterance(spokenText.value);\n bindEventsForUtterance(newUtterance);\n return newUtterance;\n });\n const speak = () => {\n synth.cancel();\n if (utterance)\n synth.speak(utterance.value);\n };\n const stop = () => {\n synth.cancel();\n isPlaying.value = false;\n };\n if (isSupported.value) {\n bindEventsForUtterance(utterance.value);\n watch(lang, (lang2) => {\n if (utterance.value && !isPlaying.value)\n utterance.value.lang = lang2;\n });\n if (options.voice) {\n watch(options.voice, () => {\n synth.cancel();\n });\n }\n watch(isPlaying, () => {\n if (isPlaying.value)\n synth.resume();\n else\n synth.pause();\n });\n }\n tryOnScopeDispose(() => {\n isPlaying.value = false;\n });\n return {\n isSupported,\n isPlaying,\n status,\n utterance,\n error,\n stop,\n toggle,\n speak\n };\n}\n\nfunction useStepper(steps, initialStep) {\n const stepsRef = ref(steps);\n const stepNames = computed(() => Array.isArray(stepsRef.value) ? stepsRef.value : Object.keys(stepsRef.value));\n const index = ref(stepNames.value.indexOf(initialStep != null ? initialStep : stepNames.value[0]));\n const current = computed(() => at(index.value));\n const isFirst = computed(() => index.value === 0);\n const isLast = computed(() => index.value === stepNames.value.length - 1);\n const next = computed(() => stepNames.value[index.value + 1]);\n const previous = computed(() => stepNames.value[index.value - 1]);\n function at(index2) {\n if (Array.isArray(stepsRef.value))\n return stepsRef.value[index2];\n return stepsRef.value[stepNames.value[index2]];\n }\n function get(step) {\n if (!stepNames.value.includes(step))\n return;\n return at(stepNames.value.indexOf(step));\n }\n function goTo(step) {\n if (stepNames.value.includes(step))\n index.value = stepNames.value.indexOf(step);\n }\n function goToNext() {\n if (isLast.value)\n return;\n index.value++;\n }\n function goToPrevious() {\n if (isFirst.value)\n return;\n index.value--;\n }\n function goBackTo(step) {\n if (isAfter(step))\n goTo(step);\n }\n function isNext(step) {\n return stepNames.value.indexOf(step) === index.value + 1;\n }\n function isPrevious(step) {\n return stepNames.value.indexOf(step) === index.value - 1;\n }\n function isCurrent(step) {\n return stepNames.value.indexOf(step) === index.value;\n }\n function isBefore(step) {\n return index.value < stepNames.value.indexOf(step);\n }\n function isAfter(step) {\n return index.value > stepNames.value.indexOf(step);\n }\n return {\n steps: stepsRef,\n stepNames,\n index,\n current,\n next,\n previous,\n isFirst,\n isLast,\n at,\n get,\n goTo,\n goToNext,\n goToPrevious,\n goBackTo,\n isNext,\n isPrevious,\n isCurrent,\n isBefore,\n isAfter\n };\n}\n\nfunction useStorageAsync(key, initialValue, storage, options = {}) {\n var _a;\n const {\n flush = \"pre\",\n deep = true,\n listenToStorageChanges = true,\n writeDefaults = true,\n mergeDefaults = false,\n shallow,\n window = defaultWindow,\n eventFilter,\n onError = (e) => {\n console.error(e);\n }\n } = options;\n const rawInit = toValue(initialValue);\n const type = guessSerializerType(rawInit);\n const data = (shallow ? shallowRef : ref)(toValue(initialValue));\n const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type];\n if (!storage) {\n try {\n storage = getSSRHandler(\"getDefaultStorageAsync\", () => {\n var _a2;\n return (_a2 = defaultWindow) == null ? void 0 : _a2.localStorage;\n })();\n } catch (e) {\n onError(e);\n }\n }\n async function read(event) {\n if (!storage || event && event.key !== key)\n return;\n try {\n const rawValue = event ? event.newValue : await storage.getItem(key);\n if (rawValue == null) {\n data.value = rawInit;\n if (writeDefaults && rawInit !== null)\n await storage.setItem(key, await serializer.write(rawInit));\n } else if (mergeDefaults) {\n const value = await serializer.read(rawValue);\n if (typeof mergeDefaults === \"function\")\n data.value = mergeDefaults(value, rawInit);\n else if (type === \"object\" && !Array.isArray(value))\n data.value = { ...rawInit, ...value };\n else data.value = value;\n } else {\n data.value = await serializer.read(rawValue);\n }\n } catch (e) {\n onError(e);\n }\n }\n read();\n if (window && listenToStorageChanges)\n useEventListener(window, \"storage\", (e) => Promise.resolve().then(() => read(e)), { passive: true });\n if (storage) {\n watchWithFilter(\n data,\n async () => {\n try {\n if (data.value == null)\n await storage.removeItem(key);\n else\n await storage.setItem(key, await serializer.write(data.value));\n } catch (e) {\n onError(e);\n }\n },\n {\n flush,\n deep,\n eventFilter\n }\n );\n }\n return data;\n}\n\nlet _id = 0;\nfunction useStyleTag(css, options = {}) {\n const isLoaded = shallowRef(false);\n const {\n document = defaultDocument,\n immediate = true,\n manual = false,\n id = `vueuse_styletag_${++_id}`\n } = options;\n const cssRef = shallowRef(css);\n let stop = () => {\n };\n const load = () => {\n if (!document)\n return;\n const el = document.getElementById(id) || document.createElement(\"style\");\n if (!el.isConnected) {\n el.id = id;\n if (options.media)\n el.media = options.media;\n document.head.appendChild(el);\n }\n if (isLoaded.value)\n return;\n stop = watch(\n cssRef,\n (value) => {\n el.textContent = value;\n },\n { immediate: true }\n );\n isLoaded.value = true;\n };\n const unload = () => {\n if (!document || !isLoaded.value)\n return;\n stop();\n document.head.removeChild(document.getElementById(id));\n isLoaded.value = false;\n };\n if (immediate && !manual)\n tryOnMounted(load);\n if (!manual)\n tryOnScopeDispose(unload);\n return {\n id,\n css: cssRef,\n unload,\n load,\n isLoaded: readonly(isLoaded)\n };\n}\n\nfunction useSwipe(target, options = {}) {\n const {\n threshold = 50,\n onSwipe,\n onSwipeEnd,\n onSwipeStart,\n passive = true\n } = options;\n const coordsStart = reactive({ x: 0, y: 0 });\n const coordsEnd = reactive({ x: 0, y: 0 });\n const diffX = computed(() => coordsStart.x - coordsEnd.x);\n const diffY = computed(() => coordsStart.y - coordsEnd.y);\n const { max, abs } = Math;\n const isThresholdExceeded = computed(() => max(abs(diffX.value), abs(diffY.value)) >= threshold);\n const isSwiping = shallowRef(false);\n const direction = computed(() => {\n if (!isThresholdExceeded.value)\n return \"none\";\n if (abs(diffX.value) > abs(diffY.value)) {\n return diffX.value > 0 ? \"left\" : \"right\";\n } else {\n return diffY.value > 0 ? \"up\" : \"down\";\n }\n });\n const getTouchEventCoords = (e) => [e.touches[0].clientX, e.touches[0].clientY];\n const updateCoordsStart = (x, y) => {\n coordsStart.x = x;\n coordsStart.y = y;\n };\n const updateCoordsEnd = (x, y) => {\n coordsEnd.x = x;\n coordsEnd.y = y;\n };\n const listenerOptions = { passive, capture: !passive };\n const onTouchEnd = (e) => {\n if (isSwiping.value)\n onSwipeEnd == null ? void 0 : onSwipeEnd(e, direction.value);\n isSwiping.value = false;\n };\n const stops = [\n useEventListener(target, \"touchstart\", (e) => {\n if (e.touches.length !== 1)\n return;\n const [x, y] = getTouchEventCoords(e);\n updateCoordsStart(x, y);\n updateCoordsEnd(x, y);\n onSwipeStart == null ? void 0 : onSwipeStart(e);\n }, listenerOptions),\n useEventListener(target, \"touchmove\", (e) => {\n if (e.touches.length !== 1)\n return;\n const [x, y] = getTouchEventCoords(e);\n updateCoordsEnd(x, y);\n if (listenerOptions.capture && !listenerOptions.passive && Math.abs(diffX.value) > Math.abs(diffY.value))\n e.preventDefault();\n if (!isSwiping.value && isThresholdExceeded.value)\n isSwiping.value = true;\n if (isSwiping.value)\n onSwipe == null ? void 0 : onSwipe(e);\n }, listenerOptions),\n useEventListener(target, [\"touchend\", \"touchcancel\"], onTouchEnd, listenerOptions)\n ];\n const stop = () => stops.forEach((s) => s());\n return {\n isSwiping,\n direction,\n coordsStart,\n coordsEnd,\n lengthX: diffX,\n lengthY: diffY,\n stop,\n // TODO: Remove in the next major version\n isPassiveEventSupported: true\n };\n}\n\nfunction useTemplateRefsList() {\n const refs = ref([]);\n refs.value.set = (el) => {\n if (el)\n refs.value.push(el);\n };\n onBeforeUpdate(() => {\n refs.value.length = 0;\n });\n return refs;\n}\n\nfunction useTextDirection(options = {}) {\n const {\n document = defaultDocument,\n selector = \"html\",\n observe = false,\n initialValue = \"ltr\"\n } = options;\n function getValue() {\n var _a, _b;\n return (_b = (_a = document == null ? void 0 : document.querySelector(selector)) == null ? void 0 : _a.getAttribute(\"dir\")) != null ? _b : initialValue;\n }\n const dir = ref(getValue());\n tryOnMounted(() => dir.value = getValue());\n if (observe && document) {\n useMutationObserver(\n document.querySelector(selector),\n () => dir.value = getValue(),\n { attributes: true }\n );\n }\n return computed({\n get() {\n return dir.value;\n },\n set(v) {\n var _a, _b;\n dir.value = v;\n if (!document)\n return;\n if (dir.value)\n (_a = document.querySelector(selector)) == null ? void 0 : _a.setAttribute(\"dir\", dir.value);\n else\n (_b = document.querySelector(selector)) == null ? void 0 : _b.removeAttribute(\"dir\");\n }\n });\n}\n\nfunction getRangesFromSelection(selection) {\n var _a;\n const rangeCount = (_a = selection.rangeCount) != null ? _a : 0;\n return Array.from({ length: rangeCount }, (_, i) => selection.getRangeAt(i));\n}\nfunction useTextSelection(options = {}) {\n const {\n window = defaultWindow\n } = options;\n const selection = ref(null);\n const text = computed(() => {\n var _a, _b;\n return (_b = (_a = selection.value) == null ? void 0 : _a.toString()) != null ? _b : \"\";\n });\n const ranges = computed(() => selection.value ? getRangesFromSelection(selection.value) : []);\n const rects = computed(() => ranges.value.map((range) => range.getBoundingClientRect()));\n function onSelectionChange() {\n selection.value = null;\n if (window)\n selection.value = window.getSelection();\n }\n if (window)\n useEventListener(window.document, \"selectionchange\", onSelectionChange, { passive: true });\n return {\n text,\n rects,\n ranges,\n selection\n };\n}\n\nfunction tryRequestAnimationFrame(window = defaultWindow, fn) {\n if (window && typeof window.requestAnimationFrame === \"function\") {\n window.requestAnimationFrame(fn);\n } else {\n fn();\n }\n}\nfunction useTextareaAutosize(options = {}) {\n var _a, _b;\n const { window = defaultWindow } = options;\n const textarea = toRef(options == null ? void 0 : options.element);\n const input = toRef((_a = options == null ? void 0 : options.input) != null ? _a : \"\");\n const styleProp = (_b = options == null ? void 0 : options.styleProp) != null ? _b : \"height\";\n const textareaScrollHeight = shallowRef(1);\n const textareaOldWidth = shallowRef(0);\n function triggerResize() {\n var _a2;\n if (!textarea.value)\n return;\n let height = \"\";\n textarea.value.style[styleProp] = \"1px\";\n textareaScrollHeight.value = (_a2 = textarea.value) == null ? void 0 : _a2.scrollHeight;\n const _styleTarget = toValue(options == null ? void 0 : options.styleTarget);\n if (_styleTarget)\n _styleTarget.style[styleProp] = `${textareaScrollHeight.value}px`;\n else\n height = `${textareaScrollHeight.value}px`;\n textarea.value.style[styleProp] = height;\n }\n watch([input, textarea], () => nextTick(triggerResize), { immediate: true });\n watch(textareaScrollHeight, () => {\n var _a2;\n return (_a2 = options == null ? void 0 : options.onResize) == null ? void 0 : _a2.call(options);\n });\n useResizeObserver(textarea, ([{ contentRect }]) => {\n if (textareaOldWidth.value === contentRect.width)\n return;\n tryRequestAnimationFrame(window, () => {\n textareaOldWidth.value = contentRect.width;\n triggerResize();\n });\n });\n if (options == null ? void 0 : options.watch)\n watch(options.watch, triggerResize, { immediate: true, deep: true });\n return {\n textarea,\n input,\n triggerResize\n };\n}\n\nfunction useThrottledRefHistory(source, options = {}) {\n const { throttle = 200, trailing = true } = options;\n const filter = throttleFilter(throttle, trailing);\n const history = useRefHistory(source, { ...options, eventFilter: filter });\n return {\n ...history\n };\n}\n\nconst DEFAULT_UNITS = [\n { max: 6e4, value: 1e3, name: \"second\" },\n { max: 276e4, value: 6e4, name: \"minute\" },\n { max: 72e6, value: 36e5, name: \"hour\" },\n { max: 5184e5, value: 864e5, name: \"day\" },\n { max: 24192e5, value: 6048e5, name: \"week\" },\n { max: 28512e6, value: 2592e6, name: \"month\" },\n { max: Number.POSITIVE_INFINITY, value: 31536e6, name: \"year\" }\n];\nconst DEFAULT_MESSAGES = {\n justNow: \"just now\",\n past: (n) => n.match(/\\d/) ? `${n} ago` : n,\n future: (n) => n.match(/\\d/) ? `in ${n}` : n,\n month: (n, past) => n === 1 ? past ? \"last month\" : \"next month\" : `${n} month${n > 1 ? \"s\" : \"\"}`,\n year: (n, past) => n === 1 ? past ? \"last year\" : \"next year\" : `${n} year${n > 1 ? \"s\" : \"\"}`,\n day: (n, past) => n === 1 ? past ? \"yesterday\" : \"tomorrow\" : `${n} day${n > 1 ? \"s\" : \"\"}`,\n week: (n, past) => n === 1 ? past ? \"last week\" : \"next week\" : `${n} week${n > 1 ? \"s\" : \"\"}`,\n hour: (n) => `${n} hour${n > 1 ? \"s\" : \"\"}`,\n minute: (n) => `${n} minute${n > 1 ? \"s\" : \"\"}`,\n second: (n) => `${n} second${n > 1 ? \"s\" : \"\"}`,\n invalid: \"\"\n};\nfunction DEFAULT_FORMATTER(date) {\n return date.toISOString().slice(0, 10);\n}\nfunction useTimeAgo(time, options = {}) {\n const {\n controls: exposeControls = false,\n updateInterval = 3e4\n } = options;\n const { now, ...controls } = useNow({ interval: updateInterval, controls: true });\n const timeAgo = computed(() => formatTimeAgo(new Date(toValue(time)), options, toValue(now)));\n if (exposeControls) {\n return {\n timeAgo,\n ...controls\n };\n } else {\n return timeAgo;\n }\n}\nfunction formatTimeAgo(from, options = {}, now = Date.now()) {\n var _a;\n const {\n max,\n messages = DEFAULT_MESSAGES,\n fullDateFormatter = DEFAULT_FORMATTER,\n units = DEFAULT_UNITS,\n showSecond = false,\n rounding = \"round\"\n } = options;\n const roundFn = typeof rounding === \"number\" ? (n) => +n.toFixed(rounding) : Math[rounding];\n const diff = +now - +from;\n const absDiff = Math.abs(diff);\n function getValue(diff2, unit) {\n return roundFn(Math.abs(diff2) / unit.value);\n }\n function format(diff2, unit) {\n const val = getValue(diff2, unit);\n const past = diff2 > 0;\n const str = applyFormat(unit.name, val, past);\n return applyFormat(past ? \"past\" : \"future\", str, past);\n }\n function applyFormat(name, val, isPast) {\n const formatter = messages[name];\n if (typeof formatter === \"function\")\n return formatter(val, isPast);\n return formatter.replace(\"{0}\", val.toString());\n }\n if (absDiff < 6e4 && !showSecond)\n return messages.justNow;\n if (typeof max === \"number\" && absDiff > max)\n return fullDateFormatter(new Date(from));\n if (typeof max === \"string\") {\n const unitMax = (_a = units.find((i) => i.name === max)) == null ? void 0 : _a.max;\n if (unitMax && absDiff > unitMax)\n return fullDateFormatter(new Date(from));\n }\n for (const [idx, unit] of units.entries()) {\n const val = getValue(diff, unit);\n if (val <= 0 && units[idx - 1])\n return format(diff, units[idx - 1]);\n if (absDiff < unit.max)\n return format(diff, unit);\n }\n return messages.invalid;\n}\n\nfunction useTimeoutPoll(fn, interval, options = {}) {\n const {\n immediate = true,\n immediateCallback = false\n } = options;\n const { start } = useTimeoutFn(loop, interval, { immediate });\n const isActive = shallowRef(false);\n async function loop() {\n if (!isActive.value)\n return;\n await fn();\n start();\n }\n function resume() {\n if (!isActive.value) {\n isActive.value = true;\n if (immediateCallback)\n fn();\n start();\n }\n }\n function pause() {\n isActive.value = false;\n }\n if (immediate && isClient)\n resume();\n tryOnScopeDispose(pause);\n return {\n isActive,\n pause,\n resume\n };\n}\n\nfunction useTimestamp(options = {}) {\n const {\n controls: exposeControls = false,\n offset = 0,\n immediate = true,\n interval = \"requestAnimationFrame\",\n callback\n } = options;\n const ts = shallowRef(timestamp() + offset);\n const update = () => ts.value = timestamp() + offset;\n const cb = callback ? () => {\n update();\n callback(ts.value);\n } : update;\n const controls = interval === \"requestAnimationFrame\" ? useRafFn(cb, { immediate }) : useIntervalFn(cb, interval, { immediate });\n if (exposeControls) {\n return {\n timestamp: ts,\n ...controls\n };\n } else {\n return ts;\n }\n}\n\nfunction useTitle(newTitle = null, options = {}) {\n var _a, _b, _c;\n const {\n document = defaultDocument,\n restoreOnUnmount = (t) => t\n } = options;\n const originalTitle = (_a = document == null ? void 0 : document.title) != null ? _a : \"\";\n const title = toRef((_b = newTitle != null ? newTitle : document == null ? void 0 : document.title) != null ? _b : null);\n const isReadonly = !!(newTitle && typeof newTitle === \"function\");\n function format(t) {\n if (!(\"titleTemplate\" in options))\n return t;\n const template = options.titleTemplate || \"%s\";\n return typeof template === \"function\" ? template(t) : toValue(template).replace(/%s/g, t);\n }\n watch(\n title,\n (newValue, oldValue) => {\n if (newValue !== oldValue && document)\n document.title = format(newValue != null ? newValue : \"\");\n },\n { immediate: true }\n );\n if (options.observe && !options.titleTemplate && document && !isReadonly) {\n useMutationObserver(\n (_c = document.head) == null ? void 0 : _c.querySelector(\"title\"),\n () => {\n if (document && document.title !== title.value)\n title.value = format(document.title);\n },\n { childList: true }\n );\n }\n tryOnScopeDispose(() => {\n if (restoreOnUnmount) {\n const restoredTitle = restoreOnUnmount(originalTitle, title.value || \"\");\n if (restoredTitle != null && document)\n document.title = restoredTitle;\n }\n });\n return title;\n}\n\nconst _TransitionPresets = {\n easeInSine: [0.12, 0, 0.39, 0],\n easeOutSine: [0.61, 1, 0.88, 1],\n easeInOutSine: [0.37, 0, 0.63, 1],\n easeInQuad: [0.11, 0, 0.5, 0],\n easeOutQuad: [0.5, 1, 0.89, 1],\n easeInOutQuad: [0.45, 0, 0.55, 1],\n easeInCubic: [0.32, 0, 0.67, 0],\n easeOutCubic: [0.33, 1, 0.68, 1],\n easeInOutCubic: [0.65, 0, 0.35, 1],\n easeInQuart: [0.5, 0, 0.75, 0],\n easeOutQuart: [0.25, 1, 0.5, 1],\n easeInOutQuart: [0.76, 0, 0.24, 1],\n easeInQuint: [0.64, 0, 0.78, 0],\n easeOutQuint: [0.22, 1, 0.36, 1],\n easeInOutQuint: [0.83, 0, 0.17, 1],\n easeInExpo: [0.7, 0, 0.84, 0],\n easeOutExpo: [0.16, 1, 0.3, 1],\n easeInOutExpo: [0.87, 0, 0.13, 1],\n easeInCirc: [0.55, 0, 1, 0.45],\n easeOutCirc: [0, 0.55, 0.45, 1],\n easeInOutCirc: [0.85, 0, 0.15, 1],\n easeInBack: [0.36, 0, 0.66, -0.56],\n easeOutBack: [0.34, 1.56, 0.64, 1],\n easeInOutBack: [0.68, -0.6, 0.32, 1.6]\n};\nconst TransitionPresets = /* @__PURE__ */ Object.assign({}, { linear: identity }, _TransitionPresets);\nfunction createEasingFunction([p0, p1, p2, p3]) {\n const a = (a1, a2) => 1 - 3 * a2 + 3 * a1;\n const b = (a1, a2) => 3 * a2 - 6 * a1;\n const c = (a1) => 3 * a1;\n const calcBezier = (t, a1, a2) => ((a(a1, a2) * t + b(a1, a2)) * t + c(a1)) * t;\n const getSlope = (t, a1, a2) => 3 * a(a1, a2) * t * t + 2 * b(a1, a2) * t + c(a1);\n const getTforX = (x) => {\n let aGuessT = x;\n for (let i = 0; i < 4; ++i) {\n const currentSlope = getSlope(aGuessT, p0, p2);\n if (currentSlope === 0)\n return aGuessT;\n const currentX = calcBezier(aGuessT, p0, p2) - x;\n aGuessT -= currentX / currentSlope;\n }\n return aGuessT;\n };\n return (x) => p0 === p1 && p2 === p3 ? x : calcBezier(getTforX(x), p1, p3);\n}\nfunction lerp(a, b, alpha) {\n return a + alpha * (b - a);\n}\nfunction toVec(t) {\n return (typeof t === \"number\" ? [t] : t) || [];\n}\nfunction executeTransition(source, from, to, options = {}) {\n var _a, _b;\n const fromVal = toValue(from);\n const toVal = toValue(to);\n const v1 = toVec(fromVal);\n const v2 = toVec(toVal);\n const duration = (_a = toValue(options.duration)) != null ? _a : 1e3;\n const startedAt = Date.now();\n const endAt = Date.now() + duration;\n const trans = typeof options.transition === \"function\" ? options.transition : (_b = toValue(options.transition)) != null ? _b : identity;\n const ease = typeof trans === \"function\" ? trans : createEasingFunction(trans);\n return new Promise((resolve) => {\n source.value = fromVal;\n const tick = () => {\n var _a2;\n if ((_a2 = options.abort) == null ? void 0 : _a2.call(options)) {\n resolve();\n return;\n }\n const now = Date.now();\n const alpha = ease((now - startedAt) / duration);\n const arr = toVec(source.value).map((n, i) => lerp(v1[i], v2[i], alpha));\n if (Array.isArray(source.value))\n source.value = arr.map((n, i) => {\n var _a3, _b2;\n return lerp((_a3 = v1[i]) != null ? _a3 : 0, (_b2 = v2[i]) != null ? _b2 : 0, alpha);\n });\n else if (typeof source.value === \"number\")\n source.value = arr[0];\n if (now < endAt) {\n requestAnimationFrame(tick);\n } else {\n source.value = toVal;\n resolve();\n }\n };\n tick();\n });\n}\nfunction useTransition(source, options = {}) {\n let currentId = 0;\n const sourceVal = () => {\n const v = toValue(source);\n return typeof v === \"number\" ? v : v.map(toValue);\n };\n const outputRef = ref(sourceVal());\n watch(sourceVal, async (to) => {\n var _a, _b;\n if (toValue(options.disabled))\n return;\n const id = ++currentId;\n if (options.delay)\n await promiseTimeout(toValue(options.delay));\n if (id !== currentId)\n return;\n const toVal = Array.isArray(to) ? to.map(toValue) : toValue(to);\n (_a = options.onStarted) == null ? void 0 : _a.call(options);\n await executeTransition(outputRef, outputRef.value, toVal, {\n ...options,\n abort: () => {\n var _a2;\n return id !== currentId || ((_a2 = options.abort) == null ? void 0 : _a2.call(options));\n }\n });\n (_b = options.onFinished) == null ? void 0 : _b.call(options);\n }, { deep: true });\n watch(() => toValue(options.disabled), (disabled) => {\n if (disabled) {\n currentId++;\n outputRef.value = sourceVal();\n }\n });\n tryOnScopeDispose(() => {\n currentId++;\n });\n return computed(() => toValue(options.disabled) ? sourceVal() : outputRef.value);\n}\n\nfunction useUrlSearchParams(mode = \"history\", options = {}) {\n const {\n initialValue = {},\n removeNullishValues = true,\n removeFalsyValues = false,\n write: enableWrite = true,\n writeMode = \"replace\",\n window = defaultWindow\n } = options;\n if (!window)\n return reactive(initialValue);\n const state = reactive({});\n function getRawParams() {\n if (mode === \"history\") {\n return window.location.search || \"\";\n } else if (mode === \"hash\") {\n const hash = window.location.hash || \"\";\n const index = hash.indexOf(\"?\");\n return index > 0 ? hash.slice(index) : \"\";\n } else {\n return (window.location.hash || \"\").replace(/^#/, \"\");\n }\n }\n function constructQuery(params) {\n const stringified = params.toString();\n if (mode === \"history\")\n return `${stringified ? `?${stringified}` : \"\"}${window.location.hash || \"\"}`;\n if (mode === \"hash-params\")\n return `${window.location.search || \"\"}${stringified ? `#${stringified}` : \"\"}`;\n const hash = window.location.hash || \"#\";\n const index = hash.indexOf(\"?\");\n if (index > 0)\n return `${window.location.search || \"\"}${hash.slice(0, index)}${stringified ? `?${stringified}` : \"\"}`;\n return `${window.location.search || \"\"}${hash}${stringified ? `?${stringified}` : \"\"}`;\n }\n function read() {\n return new URLSearchParams(getRawParams());\n }\n function updateState(params) {\n const unusedKeys = new Set(Object.keys(state));\n for (const key of params.keys()) {\n const paramsForKey = params.getAll(key);\n state[key] = paramsForKey.length > 1 ? paramsForKey : params.get(key) || \"\";\n unusedKeys.delete(key);\n }\n Array.from(unusedKeys).forEach((key) => delete state[key]);\n }\n const { pause, resume } = pausableWatch(\n state,\n () => {\n const params = new URLSearchParams(\"\");\n Object.keys(state).forEach((key) => {\n const mapEntry = state[key];\n if (Array.isArray(mapEntry))\n mapEntry.forEach((value) => params.append(key, value));\n else if (removeNullishValues && mapEntry == null)\n params.delete(key);\n else if (removeFalsyValues && !mapEntry)\n params.delete(key);\n else\n params.set(key, mapEntry);\n });\n write(params, false);\n },\n { deep: true }\n );\n function write(params, shouldUpdate) {\n pause();\n if (shouldUpdate)\n updateState(params);\n if (writeMode === \"replace\") {\n window.history.replaceState(\n window.history.state,\n window.document.title,\n window.location.pathname + constructQuery(params)\n );\n } else {\n window.history.pushState(\n window.history.state,\n window.document.title,\n window.location.pathname + constructQuery(params)\n );\n }\n resume();\n }\n function onChanged() {\n if (!enableWrite)\n return;\n write(read(), true);\n }\n const listenerOptions = { passive: true };\n useEventListener(window, \"popstate\", onChanged, listenerOptions);\n if (mode !== \"history\")\n useEventListener(window, \"hashchange\", onChanged, listenerOptions);\n const initial = read();\n if (initial.keys().next().value)\n updateState(initial);\n else\n Object.assign(state, initialValue);\n return state;\n}\n\nfunction useUserMedia(options = {}) {\n var _a, _b;\n const enabled = shallowRef((_a = options.enabled) != null ? _a : false);\n const autoSwitch = shallowRef((_b = options.autoSwitch) != null ? _b : true);\n const constraints = ref(options.constraints);\n const { navigator = defaultNavigator } = options;\n const isSupported = useSupported(() => {\n var _a2;\n return (_a2 = navigator == null ? void 0 : navigator.mediaDevices) == null ? void 0 : _a2.getUserMedia;\n });\n const stream = shallowRef();\n function getDeviceOptions(type) {\n switch (type) {\n case \"video\": {\n if (constraints.value)\n return constraints.value.video || false;\n break;\n }\n case \"audio\": {\n if (constraints.value)\n return constraints.value.audio || false;\n break;\n }\n }\n }\n async function _start() {\n if (!isSupported.value || stream.value)\n return;\n stream.value = await navigator.mediaDevices.getUserMedia({\n video: getDeviceOptions(\"video\"),\n audio: getDeviceOptions(\"audio\")\n });\n return stream.value;\n }\n function _stop() {\n var _a2;\n (_a2 = stream.value) == null ? void 0 : _a2.getTracks().forEach((t) => t.stop());\n stream.value = void 0;\n }\n function stop() {\n _stop();\n enabled.value = false;\n }\n async function start() {\n await _start();\n if (stream.value)\n enabled.value = true;\n return stream.value;\n }\n async function restart() {\n _stop();\n return await start();\n }\n watch(\n enabled,\n (v) => {\n if (v)\n _start();\n else _stop();\n },\n { immediate: true }\n );\n watch(\n constraints,\n () => {\n if (autoSwitch.value && stream.value)\n restart();\n },\n { immediate: true }\n );\n tryOnScopeDispose(() => {\n stop();\n });\n return {\n isSupported,\n stream,\n start,\n stop,\n restart,\n constraints,\n enabled,\n autoSwitch\n };\n}\n\nfunction useVModel(props, key, emit, options = {}) {\n var _a, _b, _c;\n const {\n clone = false,\n passive = false,\n eventName,\n deep = false,\n defaultValue,\n shouldEmit\n } = options;\n const vm = getCurrentInstance();\n const _emit = emit || (vm == null ? void 0 : vm.emit) || ((_a = vm == null ? void 0 : vm.$emit) == null ? void 0 : _a.bind(vm)) || ((_c = (_b = vm == null ? void 0 : vm.proxy) == null ? void 0 : _b.$emit) == null ? void 0 : _c.bind(vm == null ? void 0 : vm.proxy));\n let event = eventName;\n if (!key) {\n key = \"modelValue\";\n }\n event = event || `update:${key.toString()}`;\n const cloneFn = (val) => !clone ? val : typeof clone === \"function\" ? clone(val) : cloneFnJSON(val);\n const getValue = () => isDef(props[key]) ? cloneFn(props[key]) : defaultValue;\n const triggerEmit = (value) => {\n if (shouldEmit) {\n if (shouldEmit(value))\n _emit(event, value);\n } else {\n _emit(event, value);\n }\n };\n if (passive) {\n const initialValue = getValue();\n const proxy = ref(initialValue);\n let isUpdating = false;\n watch(\n () => props[key],\n (v) => {\n if (!isUpdating) {\n isUpdating = true;\n proxy.value = cloneFn(v);\n nextTick(() => isUpdating = false);\n }\n }\n );\n watch(\n proxy,\n (v) => {\n if (!isUpdating && (v !== props[key] || deep))\n triggerEmit(v);\n },\n { deep }\n );\n return proxy;\n } else {\n return computed({\n get() {\n return getValue();\n },\n set(value) {\n triggerEmit(value);\n }\n });\n }\n}\n\nfunction useVModels(props, emit, options = {}) {\n const ret = {};\n for (const key in props) {\n ret[key] = useVModel(\n props,\n key,\n emit,\n options\n );\n }\n return ret;\n}\n\nfunction useVibrate(options) {\n const {\n pattern = [],\n interval = 0,\n navigator = defaultNavigator\n } = options || {};\n const isSupported = useSupported(() => typeof navigator !== \"undefined\" && \"vibrate\" in navigator);\n const patternRef = toRef(pattern);\n let intervalControls;\n const vibrate = (pattern2 = patternRef.value) => {\n if (isSupported.value)\n navigator.vibrate(pattern2);\n };\n const stop = () => {\n if (isSupported.value)\n navigator.vibrate(0);\n intervalControls == null ? void 0 : intervalControls.pause();\n };\n if (interval > 0) {\n intervalControls = useIntervalFn(\n vibrate,\n interval,\n {\n immediate: false,\n immediateCallback: false\n }\n );\n }\n return {\n isSupported,\n pattern,\n intervalControls,\n vibrate,\n stop\n };\n}\n\nfunction useVirtualList(list, options) {\n const { containerStyle, wrapperProps, scrollTo, calculateRange, currentList, containerRef } = \"itemHeight\" in options ? useVerticalVirtualList(options, list) : useHorizontalVirtualList(options, list);\n return {\n list: currentList,\n scrollTo,\n containerProps: {\n ref: containerRef,\n onScroll: () => {\n calculateRange();\n },\n style: containerStyle\n },\n wrapperProps\n };\n}\nfunction useVirtualListResources(list) {\n const containerRef = shallowRef(null);\n const size = useElementSize(containerRef);\n const currentList = ref([]);\n const source = shallowRef(list);\n const state = ref({ start: 0, end: 10 });\n return { state, source, currentList, size, containerRef };\n}\nfunction createGetViewCapacity(state, source, itemSize) {\n return (containerSize) => {\n if (typeof itemSize === \"number\")\n return Math.ceil(containerSize / itemSize);\n const { start = 0 } = state.value;\n let sum = 0;\n let capacity = 0;\n for (let i = start; i < source.value.length; i++) {\n const size = itemSize(i);\n sum += size;\n capacity = i;\n if (sum > containerSize)\n break;\n }\n return capacity - start;\n };\n}\nfunction createGetOffset(source, itemSize) {\n return (scrollDirection) => {\n if (typeof itemSize === \"number\")\n return Math.floor(scrollDirection / itemSize) + 1;\n let sum = 0;\n let offset = 0;\n for (let i = 0; i < source.value.length; i++) {\n const size = itemSize(i);\n sum += size;\n if (sum >= scrollDirection) {\n offset = i;\n break;\n }\n }\n return offset + 1;\n };\n}\nfunction createCalculateRange(type, overscan, getOffset, getViewCapacity, { containerRef, state, currentList, source }) {\n return () => {\n const element = containerRef.value;\n if (element) {\n const offset = getOffset(type === \"vertical\" ? element.scrollTop : element.scrollLeft);\n const viewCapacity = getViewCapacity(type === \"vertical\" ? element.clientHeight : element.clientWidth);\n const from = offset - overscan;\n const to = offset + viewCapacity + overscan;\n state.value = {\n start: from < 0 ? 0 : from,\n end: to > source.value.length ? source.value.length : to\n };\n currentList.value = source.value.slice(state.value.start, state.value.end).map((ele, index) => ({\n data: ele,\n index: index + state.value.start\n }));\n }\n };\n}\nfunction createGetDistance(itemSize, source) {\n return (index) => {\n if (typeof itemSize === \"number\") {\n const size2 = index * itemSize;\n return size2;\n }\n const size = source.value.slice(0, index).reduce((sum, _, i) => sum + itemSize(i), 0);\n return size;\n };\n}\nfunction useWatchForSizes(size, list, containerRef, calculateRange) {\n watch([size.width, size.height, list, containerRef], () => {\n calculateRange();\n });\n}\nfunction createComputedTotalSize(itemSize, source) {\n return computed(() => {\n if (typeof itemSize === \"number\")\n return source.value.length * itemSize;\n return source.value.reduce((sum, _, index) => sum + itemSize(index), 0);\n });\n}\nconst scrollToDictionaryForElementScrollKey = {\n horizontal: \"scrollLeft\",\n vertical: \"scrollTop\"\n};\nfunction createScrollTo(type, calculateRange, getDistance, containerRef) {\n return (index) => {\n if (containerRef.value) {\n containerRef.value[scrollToDictionaryForElementScrollKey[type]] = getDistance(index);\n calculateRange();\n }\n };\n}\nfunction useHorizontalVirtualList(options, list) {\n const resources = useVirtualListResources(list);\n const { state, source, currentList, size, containerRef } = resources;\n const containerStyle = { overflowX: \"auto\" };\n const { itemWidth, overscan = 5 } = options;\n const getViewCapacity = createGetViewCapacity(state, source, itemWidth);\n const getOffset = createGetOffset(source, itemWidth);\n const calculateRange = createCalculateRange(\"horizontal\", overscan, getOffset, getViewCapacity, resources);\n const getDistanceLeft = createGetDistance(itemWidth, source);\n const offsetLeft = computed(() => getDistanceLeft(state.value.start));\n const totalWidth = createComputedTotalSize(itemWidth, source);\n useWatchForSizes(size, list, containerRef, calculateRange);\n const scrollTo = createScrollTo(\"horizontal\", calculateRange, getDistanceLeft, containerRef);\n const wrapperProps = computed(() => {\n return {\n style: {\n height: \"100%\",\n width: `${totalWidth.value - offsetLeft.value}px`,\n marginLeft: `${offsetLeft.value}px`,\n display: \"flex\"\n }\n };\n });\n return {\n scrollTo,\n calculateRange,\n wrapperProps,\n containerStyle,\n currentList,\n containerRef\n };\n}\nfunction useVerticalVirtualList(options, list) {\n const resources = useVirtualListResources(list);\n const { state, source, currentList, size, containerRef } = resources;\n const containerStyle = { overflowY: \"auto\" };\n const { itemHeight, overscan = 5 } = options;\n const getViewCapacity = createGetViewCapacity(state, source, itemHeight);\n const getOffset = createGetOffset(source, itemHeight);\n const calculateRange = createCalculateRange(\"vertical\", overscan, getOffset, getViewCapacity, resources);\n const getDistanceTop = createGetDistance(itemHeight, source);\n const offsetTop = computed(() => getDistanceTop(state.value.start));\n const totalHeight = createComputedTotalSize(itemHeight, source);\n useWatchForSizes(size, list, containerRef, calculateRange);\n const scrollTo = createScrollTo(\"vertical\", calculateRange, getDistanceTop, containerRef);\n const wrapperProps = computed(() => {\n return {\n style: {\n width: \"100%\",\n height: `${totalHeight.value - offsetTop.value}px`,\n marginTop: `${offsetTop.value}px`\n }\n };\n });\n return {\n calculateRange,\n scrollTo,\n containerStyle,\n wrapperProps,\n currentList,\n containerRef\n };\n}\n\nfunction useWakeLock(options = {}) {\n const {\n navigator = defaultNavigator,\n document = defaultDocument\n } = options;\n const requestedType = shallowRef(false);\n const sentinel = shallowRef(null);\n const documentVisibility = useDocumentVisibility({ document });\n const isSupported = useSupported(() => navigator && \"wakeLock\" in navigator);\n const isActive = computed(() => !!sentinel.value && documentVisibility.value === \"visible\");\n if (isSupported.value) {\n useEventListener(sentinel, \"release\", () => {\n var _a, _b;\n requestedType.value = (_b = (_a = sentinel.value) == null ? void 0 : _a.type) != null ? _b : false;\n }, { passive: true });\n whenever(\n () => documentVisibility.value === \"visible\" && (document == null ? void 0 : document.visibilityState) === \"visible\" && requestedType.value,\n (type) => {\n requestedType.value = false;\n forceRequest(type);\n }\n );\n }\n async function forceRequest(type) {\n var _a;\n await ((_a = sentinel.value) == null ? void 0 : _a.release());\n sentinel.value = isSupported.value ? await navigator.wakeLock.request(type) : null;\n }\n async function request(type) {\n if (documentVisibility.value === \"visible\")\n await forceRequest(type);\n else\n requestedType.value = type;\n }\n async function release() {\n requestedType.value = false;\n const s = sentinel.value;\n sentinel.value = null;\n await (s == null ? void 0 : s.release());\n }\n return {\n sentinel,\n isSupported,\n isActive,\n request,\n forceRequest,\n release\n };\n}\n\nfunction useWebNotification(options = {}) {\n const {\n window = defaultWindow,\n requestPermissions: _requestForPermissions = true\n } = options;\n const defaultWebNotificationOptions = options;\n const isSupported = useSupported(() => {\n if (!window || !(\"Notification\" in window))\n return false;\n if (Notification.permission === \"granted\")\n return true;\n try {\n const notification2 = new Notification(\"\");\n notification2.onshow = () => {\n notification2.close();\n };\n } catch (e) {\n if (e.name === \"TypeError\")\n return false;\n }\n return true;\n });\n const permissionGranted = shallowRef(isSupported.value && \"permission\" in Notification && Notification.permission === \"granted\");\n const notification = ref(null);\n const ensurePermissions = async () => {\n if (!isSupported.value)\n return;\n if (!permissionGranted.value && Notification.permission !== \"denied\") {\n const result = await Notification.requestPermission();\n if (result === \"granted\")\n permissionGranted.value = true;\n }\n return permissionGranted.value;\n };\n const { on: onClick, trigger: clickTrigger } = createEventHook();\n const { on: onShow, trigger: showTrigger } = createEventHook();\n const { on: onError, trigger: errorTrigger } = createEventHook();\n const { on: onClose, trigger: closeTrigger } = createEventHook();\n const show = async (overrides) => {\n if (!isSupported.value || !permissionGranted.value)\n return;\n const options2 = Object.assign({}, defaultWebNotificationOptions, overrides);\n notification.value = new Notification(options2.title || \"\", options2);\n notification.value.onclick = clickTrigger;\n notification.value.onshow = showTrigger;\n notification.value.onerror = errorTrigger;\n notification.value.onclose = closeTrigger;\n return notification.value;\n };\n const close = () => {\n if (notification.value)\n notification.value.close();\n notification.value = null;\n };\n if (_requestForPermissions)\n tryOnMounted(ensurePermissions);\n tryOnScopeDispose(close);\n if (isSupported.value && window) {\n const document = window.document;\n useEventListener(document, \"visibilitychange\", (e) => {\n e.preventDefault();\n if (document.visibilityState === \"visible\") {\n close();\n }\n });\n }\n return {\n isSupported,\n notification,\n ensurePermissions,\n permissionGranted,\n show,\n close,\n onClick,\n onShow,\n onError,\n onClose\n };\n}\n\nconst DEFAULT_PING_MESSAGE = \"ping\";\nfunction resolveNestedOptions(options) {\n if (options === true)\n return {};\n return options;\n}\nfunction useWebSocket(url, options = {}) {\n const {\n onConnected,\n onDisconnected,\n onError,\n onMessage,\n immediate = true,\n autoConnect = true,\n autoClose = true,\n protocols = []\n } = options;\n const data = ref(null);\n const status = shallowRef(\"CLOSED\");\n const wsRef = ref();\n const urlRef = toRef(url);\n let heartbeatPause;\n let heartbeatResume;\n let explicitlyClosed = false;\n let retried = 0;\n let bufferedData = [];\n let retryTimeout;\n let pongTimeoutWait;\n const _sendBuffer = () => {\n if (bufferedData.length && wsRef.value && status.value === \"OPEN\") {\n for (const buffer of bufferedData)\n wsRef.value.send(buffer);\n bufferedData = [];\n }\n };\n const resetRetry = () => {\n if (retryTimeout != null) {\n clearTimeout(retryTimeout);\n retryTimeout = void 0;\n }\n };\n const resetHeartbeat = () => {\n clearTimeout(pongTimeoutWait);\n pongTimeoutWait = void 0;\n };\n const close = (code = 1e3, reason) => {\n resetRetry();\n if (!isClient && !isWorker || !wsRef.value)\n return;\n explicitlyClosed = true;\n resetHeartbeat();\n heartbeatPause == null ? void 0 : heartbeatPause();\n wsRef.value.close(code, reason);\n wsRef.value = void 0;\n };\n const send = (data2, useBuffer = true) => {\n if (!wsRef.value || status.value !== \"OPEN\") {\n if (useBuffer)\n bufferedData.push(data2);\n return false;\n }\n _sendBuffer();\n wsRef.value.send(data2);\n return true;\n };\n const _init = () => {\n if (explicitlyClosed || typeof urlRef.value === \"undefined\")\n return;\n const ws = new WebSocket(urlRef.value, protocols);\n wsRef.value = ws;\n status.value = \"CONNECTING\";\n ws.onopen = () => {\n status.value = \"OPEN\";\n retried = 0;\n onConnected == null ? void 0 : onConnected(ws);\n heartbeatResume == null ? void 0 : heartbeatResume();\n _sendBuffer();\n };\n ws.onclose = (ev) => {\n status.value = \"CLOSED\";\n resetHeartbeat();\n heartbeatPause == null ? void 0 : heartbeatPause();\n onDisconnected == null ? void 0 : onDisconnected(ws, ev);\n if (!explicitlyClosed && options.autoReconnect && (wsRef.value == null || ws === wsRef.value)) {\n const {\n retries = -1,\n delay = 1e3,\n onFailed\n } = resolveNestedOptions(options.autoReconnect);\n const checkRetires = typeof retries === \"function\" ? retries : () => typeof retries === \"number\" && (retries < 0 || retried < retries);\n if (checkRetires(retried)) {\n retried += 1;\n retryTimeout = setTimeout(_init, delay);\n } else {\n onFailed == null ? void 0 : onFailed();\n }\n }\n };\n ws.onerror = (e) => {\n onError == null ? void 0 : onError(ws, e);\n };\n ws.onmessage = (e) => {\n if (options.heartbeat) {\n resetHeartbeat();\n const {\n message = DEFAULT_PING_MESSAGE,\n responseMessage = message\n } = resolveNestedOptions(options.heartbeat);\n if (e.data === toValue(responseMessage))\n return;\n }\n data.value = e.data;\n onMessage == null ? void 0 : onMessage(ws, e);\n };\n };\n if (options.heartbeat) {\n const {\n message = DEFAULT_PING_MESSAGE,\n interval = 1e3,\n pongTimeout = 1e3\n } = resolveNestedOptions(options.heartbeat);\n const { pause, resume } = useIntervalFn(\n () => {\n send(toValue(message), false);\n if (pongTimeoutWait != null)\n return;\n pongTimeoutWait = setTimeout(() => {\n close();\n explicitlyClosed = false;\n }, pongTimeout);\n },\n interval,\n { immediate: false }\n );\n heartbeatPause = pause;\n heartbeatResume = resume;\n }\n if (autoClose) {\n if (isClient)\n useEventListener(\"beforeunload\", () => close(), { passive: true });\n tryOnScopeDispose(close);\n }\n const open = () => {\n if (!isClient && !isWorker)\n return;\n close();\n explicitlyClosed = false;\n retried = 0;\n _init();\n };\n if (immediate)\n open();\n if (autoConnect)\n watch(urlRef, open);\n return {\n data,\n status,\n close,\n send,\n open,\n ws: wsRef\n };\n}\n\nfunction useWebWorker(arg0, workerOptions, options) {\n const {\n window = defaultWindow\n } = options != null ? options : {};\n const data = ref(null);\n const worker = shallowRef();\n const post = (...args) => {\n if (!worker.value)\n return;\n worker.value.postMessage(...args);\n };\n const terminate = function terminate2() {\n if (!worker.value)\n return;\n worker.value.terminate();\n };\n if (window) {\n if (typeof arg0 === \"string\")\n worker.value = new Worker(arg0, workerOptions);\n else if (typeof arg0 === \"function\")\n worker.value = arg0();\n else\n worker.value = arg0;\n worker.value.onmessage = (e) => {\n data.value = e.data;\n };\n tryOnScopeDispose(() => {\n if (worker.value)\n worker.value.terminate();\n });\n }\n return {\n data,\n post,\n terminate,\n worker\n };\n}\n\nfunction depsParser(deps, localDeps) {\n if (deps.length === 0 && localDeps.length === 0)\n return \"\";\n const depsString = deps.map((dep) => `'${dep}'`).toString();\n const depsFunctionString = localDeps.filter((dep) => typeof dep === \"function\").map((fn) => {\n const str = fn.toString();\n if (str.trim().startsWith(\"function\")) {\n return str;\n } else {\n const name = fn.name;\n return `const ${name} = ${str}`;\n }\n }).join(\";\");\n const importString = `importScripts(${depsString});`;\n return `${depsString.trim() === \"\" ? \"\" : importString} ${depsFunctionString}`;\n}\n\nfunction jobRunner(userFunc) {\n return (e) => {\n const userFuncArgs = e.data[0];\n return Promise.resolve(userFunc.apply(void 0, userFuncArgs)).then((result) => {\n postMessage([\"SUCCESS\", result]);\n }).catch((error) => {\n postMessage([\"ERROR\", error]);\n });\n };\n}\n\nfunction createWorkerBlobUrl(fn, deps, localDeps) {\n const blobCode = `${depsParser(deps, localDeps)}; onmessage=(${jobRunner})(${fn})`;\n const blob = new Blob([blobCode], { type: \"text/javascript\" });\n const url = URL.createObjectURL(blob);\n return url;\n}\n\nfunction useWebWorkerFn(fn, options = {}) {\n const {\n dependencies = [],\n localDependencies = [],\n timeout,\n window = defaultWindow\n } = options;\n const worker = ref();\n const workerStatus = shallowRef(\"PENDING\");\n const promise = ref({});\n const timeoutId = shallowRef();\n const workerTerminate = (status = \"PENDING\") => {\n if (worker.value && worker.value._url && window) {\n worker.value.terminate();\n URL.revokeObjectURL(worker.value._url);\n promise.value = {};\n worker.value = void 0;\n window.clearTimeout(timeoutId.value);\n workerStatus.value = status;\n }\n };\n workerTerminate();\n tryOnScopeDispose(workerTerminate);\n const generateWorker = () => {\n const blobUrl = createWorkerBlobUrl(fn, dependencies, localDependencies);\n const newWorker = new Worker(blobUrl);\n newWorker._url = blobUrl;\n newWorker.onmessage = (e) => {\n const { resolve = () => {\n }, reject = () => {\n } } = promise.value;\n const [status, result] = e.data;\n switch (status) {\n case \"SUCCESS\":\n resolve(result);\n workerTerminate(status);\n break;\n default:\n reject(result);\n workerTerminate(\"ERROR\");\n break;\n }\n };\n newWorker.onerror = (e) => {\n const { reject = () => {\n } } = promise.value;\n e.preventDefault();\n reject(e);\n workerTerminate(\"ERROR\");\n };\n if (timeout) {\n timeoutId.value = setTimeout(\n () => workerTerminate(\"TIMEOUT_EXPIRED\"),\n timeout\n );\n }\n return newWorker;\n };\n const callWorker = (...fnArgs) => new Promise((resolve, reject) => {\n var _a;\n promise.value = {\n resolve,\n reject\n };\n (_a = worker.value) == null ? void 0 : _a.postMessage([[...fnArgs]]);\n workerStatus.value = \"RUNNING\";\n });\n const workerFn = (...fnArgs) => {\n if (workerStatus.value === \"RUNNING\") {\n console.error(\n \"[useWebWorkerFn] You can only run one instance of the worker at a time.\"\n );\n return Promise.reject();\n }\n worker.value = generateWorker();\n return callWorker(...fnArgs);\n };\n return {\n workerFn,\n workerStatus,\n workerTerminate\n };\n}\n\nfunction useWindowFocus(options = {}) {\n const { window = defaultWindow } = options;\n if (!window)\n return shallowRef(false);\n const focused = shallowRef(window.document.hasFocus());\n const listenerOptions = { passive: true };\n useEventListener(window, \"blur\", () => {\n focused.value = false;\n }, listenerOptions);\n useEventListener(window, \"focus\", () => {\n focused.value = true;\n }, listenerOptions);\n return focused;\n}\n\nfunction useWindowScroll(options = {}) {\n const { window = defaultWindow, ...rest } = options;\n return useScroll(window, rest);\n}\n\nfunction useWindowSize(options = {}) {\n const {\n window = defaultWindow,\n initialWidth = Number.POSITIVE_INFINITY,\n initialHeight = Number.POSITIVE_INFINITY,\n listenOrientation = true,\n includeScrollbar = true,\n type = \"inner\"\n } = options;\n const width = shallowRef(initialWidth);\n const height = shallowRef(initialHeight);\n const update = () => {\n if (window) {\n if (type === \"outer\") {\n width.value = window.outerWidth;\n height.value = window.outerHeight;\n } else if (type === \"visual\" && window.visualViewport) {\n const { width: visualViewportWidth, height: visualViewportHeight, scale } = window.visualViewport;\n width.value = Math.round(visualViewportWidth * scale);\n height.value = Math.round(visualViewportHeight * scale);\n } else if (includeScrollbar) {\n width.value = window.innerWidth;\n height.value = window.innerHeight;\n } else {\n width.value = window.document.documentElement.clientWidth;\n height.value = window.document.documentElement.clientHeight;\n }\n }\n };\n update();\n tryOnMounted(update);\n const listenerOptions = { passive: true };\n useEventListener(\"resize\", update, listenerOptions);\n if (window && type === \"visual\" && window.visualViewport) {\n useEventListener(window.visualViewport, \"resize\", update, listenerOptions);\n }\n if (listenOrientation) {\n const matches = useMediaQuery(\"(orientation: portrait)\");\n watch(matches, () => update());\n }\n return { width, height };\n}\n\nexport { DefaultMagicKeysAliasMap, StorageSerializers, TransitionPresets, computedAsync as asyncComputed, breakpointsAntDesign, breakpointsBootstrapV5, breakpointsElement, breakpointsMasterCss, breakpointsPrimeFlex, breakpointsQuasar, breakpointsSematic, breakpointsTailwind, breakpointsVuetify, breakpointsVuetifyV2, breakpointsVuetifyV3, cloneFnJSON, computedAsync, computedInject, createFetch, createReusableTemplate, createTemplatePromise, createUnrefFn, customStorageEventName, defaultDocument, defaultLocation, defaultNavigator, defaultWindow, executeTransition, formatTimeAgo, getSSRHandler, mapGamepadToXbox360Controller, onClickOutside, onElementRemoval, onKeyDown, onKeyPressed, onKeyStroke, onKeyUp, onLongPress, onStartTyping, provideSSRWidth, setSSRHandler, templateRef, unrefElement, useActiveElement, useAnimate, useAsyncQueue, useAsyncState, useBase64, useBattery, useBluetooth, useBreakpoints, useBroadcastChannel, useBrowserLocation, useCached, useClipboard, useClipboardItems, useCloned, useColorMode, useConfirmDialog, useCountdown, useCssVar, useCurrentElement, useCycleList, useDark, useDebouncedRefHistory, useDeviceMotion, useDeviceOrientation, useDevicePixelRatio, useDevicesList, useDisplayMedia, useDocumentVisibility, useDraggable, useDropZone, useElementBounding, useElementByPoint, useElementHover, useElementSize, useElementVisibility, useEventBus, useEventListener, useEventSource, useEyeDropper, useFavicon, useFetch, useFileDialog, useFileSystemAccess, useFocus, useFocusWithin, useFps, useFullscreen, useGamepad, useGeolocation, useIdle, useImage, useInfiniteScroll, useIntersectionObserver, useKeyModifier, useLocalStorage, useMagicKeys, useManualRefHistory, useMediaControls, useMediaQuery, useMemoize, useMemory, useMounted, useMouse, useMouseInElement, useMousePressed, useMutationObserver, useNavigatorLanguage, useNetwork, useNow, useObjectUrl, useOffsetPagination, useOnline, usePageLeave, useParallax, useParentElement, usePerformanceObserver, usePermission, usePointer, usePointerLock, usePointerSwipe, usePreferredColorScheme, usePreferredContrast, usePreferredDark, usePreferredLanguages, usePreferredReducedMotion, usePreferredReducedTransparency, usePrevious, useRafFn, useRefHistory, useResizeObserver, useSSRWidth, useScreenOrientation, useScreenSafeArea, useScriptTag, useScroll, useScrollLock, useSessionStorage, useShare, useSorted, useSpeechRecognition, useSpeechSynthesis, useStepper, useStorage, useStorageAsync, useStyleTag, useSupported, useSwipe, useTemplateRefsList, useTextDirection, useTextSelection, useTextareaAutosize, useThrottledRefHistory, useTimeAgo, useTimeoutPoll, useTimestamp, useTitle, useTransition, useUrlSearchParams, useUserMedia, useVModel, useVModels, useVibrate, useVirtualList, useWakeLock, useWebNotification, useWebSocket, useWebWorker, useWebWorkerFn, useWindowFocus, useWindowScroll, useWindowSize };\n"], + "mappings": "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", + "names": ["get", "set", "ref", "keys", "invoke", "toRef", "toRefs", "toValue", "window", "document", "timestamp", "navigator", "events", "getValue", "ref", "defaults", "toRef", "set", "onUpdated", "preventDefault", "toRefs", "now", "keys", "get", "isReadonly"] +} diff --git a/docs/.vitepress/cache/deps/chunk-LE5NDSFD.js b/docs/.vitepress/cache/deps/chunk-LE5NDSFD.js new file mode 100644 index 0000000..42925ac --- /dev/null +++ b/docs/.vitepress/cache/deps/chunk-LE5NDSFD.js @@ -0,0 +1,12824 @@ +// node_modules/@vue/shared/dist/shared.esm-bundler.js +function makeMap(str) { + const map2 = /* @__PURE__ */ Object.create(null); + for (const key of str.split(",")) map2[key] = 1; + return (val) => val in map2; +} +var EMPTY_OBJ = true ? Object.freeze({}) : {}; +var EMPTY_ARR = true ? Object.freeze([]) : []; +var NOOP = () => { +}; +var NO = () => false; +var isOn = (key) => key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && // uppercase letter +(key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97); +var isModelListener = (key) => key.startsWith("onUpdate:"); +var extend = Object.assign; +var remove = (arr, el) => { + const i = arr.indexOf(el); + if (i > -1) { + arr.splice(i, 1); + } +}; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var hasOwn = (val, key) => hasOwnProperty.call(val, key); +var isArray = Array.isArray; +var isMap = (val) => toTypeString(val) === "[object Map]"; +var isSet = (val) => toTypeString(val) === "[object Set]"; +var isDate = (val) => toTypeString(val) === "[object Date]"; +var isRegExp = (val) => toTypeString(val) === "[object RegExp]"; +var isFunction = (val) => typeof val === "function"; +var isString = (val) => typeof val === "string"; +var isSymbol = (val) => typeof val === "symbol"; +var isObject = (val) => val !== null && typeof val === "object"; +var isPromise = (val) => { + return (isObject(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch); +}; +var objectToString = Object.prototype.toString; +var toTypeString = (value) => objectToString.call(value); +var toRawType = (value) => { + return toTypeString(value).slice(8, -1); +}; +var isPlainObject = (val) => toTypeString(val) === "[object Object]"; +var isIntegerKey = (key) => isString(key) && key !== "NaN" && key[0] !== "-" && "" + parseInt(key, 10) === key; +var isReservedProp = makeMap( + // the leading comma is intentional so empty string "" is also included + ",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted" +); +var isBuiltInDirective = makeMap( + "bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo" +); +var cacheStringFunction = (fn) => { + const cache = /* @__PURE__ */ Object.create(null); + return (str) => { + const hit = cache[str]; + return hit || (cache[str] = fn(str)); + }; +}; +var camelizeRE = /-\w/g; +var camelize = cacheStringFunction( + (str) => { + return str.replace(camelizeRE, (c) => c.slice(1).toUpperCase()); + } +); +var hyphenateRE = /\B([A-Z])/g; +var hyphenate = cacheStringFunction( + (str) => str.replace(hyphenateRE, "-$1").toLowerCase() +); +var capitalize = cacheStringFunction((str) => { + return str.charAt(0).toUpperCase() + str.slice(1); +}); +var toHandlerKey = cacheStringFunction( + (str) => { + const s = str ? `on${capitalize(str)}` : ``; + return s; + } +); +var hasChanged = (value, oldValue) => !Object.is(value, oldValue); +var invokeArrayFns = (fns, ...arg) => { + for (let i = 0; i < fns.length; i++) { + fns[i](...arg); + } +}; +var def = (obj, key, value, writable = false) => { + Object.defineProperty(obj, key, { + configurable: true, + enumerable: false, + writable, + value + }); +}; +var looseToNumber = (val) => { + const n = parseFloat(val); + return isNaN(n) ? val : n; +}; +var toNumber = (val) => { + const n = isString(val) ? Number(val) : NaN; + return isNaN(n) ? val : n; +}; +var _globalThis; +var getGlobalThis = () => { + return _globalThis || (_globalThis = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}); +}; +var GLOBALS_ALLOWED = "Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error,Symbol"; +var isGloballyAllowed = makeMap(GLOBALS_ALLOWED); +function normalizeStyle(value) { + if (isArray(value)) { + const res = {}; + for (let i = 0; i < value.length; i++) { + const item = value[i]; + const normalized = isString(item) ? parseStringStyle(item) : normalizeStyle(item); + if (normalized) { + for (const key in normalized) { + res[key] = normalized[key]; + } + } + } + return res; + } else if (isString(value) || isObject(value)) { + return value; + } +} +var listDelimiterRE = /;(?![^(]*\))/g; +var propertyDelimiterRE = /:([^]+)/; +var styleCommentRE = /\/\*[^]*?\*\//g; +function parseStringStyle(cssText) { + const ret = {}; + cssText.replace(styleCommentRE, "").split(listDelimiterRE).forEach((item) => { + if (item) { + const tmp = item.split(propertyDelimiterRE); + tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim()); + } + }); + return ret; +} +function stringifyStyle(styles) { + if (!styles) return ""; + if (isString(styles)) return styles; + let ret = ""; + for (const key in styles) { + const value = styles[key]; + if (isString(value) || typeof value === "number") { + const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key); + ret += `${normalizedKey}:${value};`; + } + } + return ret; +} +function normalizeClass(value) { + let res = ""; + if (isString(value)) { + res = value; + } else if (isArray(value)) { + for (let i = 0; i < value.length; i++) { + const normalized = normalizeClass(value[i]); + if (normalized) { + res += normalized + " "; + } + } + } else if (isObject(value)) { + for (const name in value) { + if (value[name]) { + res += name + " "; + } + } + } + return res.trim(); +} +function normalizeProps(props) { + if (!props) return null; + let { class: klass, style } = props; + if (klass && !isString(klass)) { + props.class = normalizeClass(klass); + } + if (style) { + props.style = normalizeStyle(style); + } + return props; +} +var HTML_TAGS = "html,body,base,head,link,meta,style,title,address,article,aside,footer,header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,summary,template,blockquote,iframe,tfoot"; +var SVG_TAGS = "svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,feDistantLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,text,textPath,title,tspan,unknown,use,view"; +var MATH_TAGS = "annotation,annotation-xml,maction,maligngroup,malignmark,math,menclose,merror,mfenced,mfrac,mfraction,mglyph,mi,mlabeledtr,mlongdiv,mmultiscripts,mn,mo,mover,mpadded,mphantom,mprescripts,mroot,mrow,ms,mscarries,mscarry,msgroup,msline,mspace,msqrt,msrow,mstack,mstyle,msub,msubsup,msup,mtable,mtd,mtext,mtr,munder,munderover,none,semantics"; +var VOID_TAGS = "area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr"; +var isHTMLTag = makeMap(HTML_TAGS); +var isSVGTag = makeMap(SVG_TAGS); +var isMathMLTag = makeMap(MATH_TAGS); +var isVoidTag = makeMap(VOID_TAGS); +var specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`; +var isSpecialBooleanAttr = makeMap(specialBooleanAttrs); +var isBooleanAttr = makeMap( + specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected` +); +function includeBooleanAttr(value) { + return !!value || value === ""; +} +var isKnownHtmlAttr = makeMap( + `accept,accept-charset,accesskey,action,align,allow,alt,async,autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,border,buffered,capture,challenge,charset,checked,cite,class,code,codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,formaction,formenctype,formmethod,formnovalidate,formtarget,headers,height,hidden,high,href,hreflang,http-equiv,icon,id,importance,inert,integrity,ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,target,title,translate,type,usemap,value,width,wrap` +); +var isKnownSvgAttr = makeMap( + `xmlns,accent-height,accumulate,additive,alignment-baseline,alphabetic,amplitude,arabic-form,ascent,attributeName,attributeType,azimuth,baseFrequency,baseline-shift,baseProfile,bbox,begin,bias,by,calcMode,cap-height,class,clip,clipPathUnits,clip-path,clip-rule,color,color-interpolation,color-interpolation-filters,color-profile,color-rendering,contentScriptType,contentStyleType,crossorigin,cursor,cx,cy,d,decelerate,descent,diffuseConstant,direction,display,divisor,dominant-baseline,dur,dx,dy,edgeMode,elevation,enable-background,end,exponent,fill,fill-opacity,fill-rule,filter,filterRes,filterUnits,flood-color,flood-opacity,font-family,font-size,font-size-adjust,font-stretch,font-style,font-variant,font-weight,format,from,fr,fx,fy,g1,g2,glyph-name,glyph-orientation-horizontal,glyph-orientation-vertical,glyphRef,gradientTransform,gradientUnits,hanging,height,href,hreflang,horiz-adv-x,horiz-origin-x,id,ideographic,image-rendering,in,in2,intercept,k,k1,k2,k3,k4,kernelMatrix,kernelUnitLength,kerning,keyPoints,keySplines,keyTimes,lang,lengthAdjust,letter-spacing,lighting-color,limitingConeAngle,local,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mask,maskContentUnits,maskUnits,mathematical,max,media,method,min,mode,name,numOctaves,offset,opacity,operator,order,orient,orientation,origin,overflow,overline-position,overline-thickness,panose-1,paint-order,path,pathLength,patternContentUnits,patternTransform,patternUnits,ping,pointer-events,points,pointsAtX,pointsAtY,pointsAtZ,preserveAlpha,preserveAspectRatio,primitiveUnits,r,radius,referrerPolicy,refX,refY,rel,rendering-intent,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,result,rotate,rx,ry,scale,seed,shape-rendering,slope,spacing,specularConstant,specularExponent,speed,spreadMethod,startOffset,stdDeviation,stemh,stemv,stitchTiles,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,string,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,style,surfaceScale,systemLanguage,tabindex,tableValues,target,targetX,targetY,text-anchor,text-decoration,text-rendering,textLength,to,transform,transform-origin,type,u1,u2,underline-position,underline-thickness,unicode,unicode-bidi,unicode-range,units-per-em,v-alphabetic,v-hanging,v-ideographic,v-mathematical,values,vector-effect,version,vert-adv-y,vert-origin-x,vert-origin-y,viewBox,viewTarget,visibility,width,widths,word-spacing,writing-mode,x,x-height,x1,x2,xChannelSelector,xlink:actuate,xlink:arcrole,xlink:href,xlink:role,xlink:show,xlink:title,xlink:type,xmlns:xlink,xml:base,xml:lang,xml:space,y,y1,y2,yChannelSelector,z,zoomAndPan` +); +var isKnownMathMLAttr = makeMap( + `accent,accentunder,actiontype,align,alignmentscope,altimg,altimg-height,altimg-valign,altimg-width,alttext,bevelled,close,columnsalign,columnlines,columnspan,denomalign,depth,dir,display,displaystyle,encoding,equalcolumns,equalrows,fence,fontstyle,fontweight,form,frame,framespacing,groupalign,height,href,id,indentalign,indentalignfirst,indentalignlast,indentshift,indentshiftfirst,indentshiftlast,indextype,justify,largetop,largeop,lquote,lspace,mathbackground,mathcolor,mathsize,mathvariant,maxsize,minlabelspacing,mode,other,overflow,position,rowalign,rowlines,rowspan,rquote,rspace,scriptlevel,scriptminsize,scriptsizemultiplier,selection,separator,separators,shift,side,src,stackalign,stretchy,subscriptshift,superscriptshift,symmetric,voffset,width,widths,xlink:href,xlink:show,xlink:type,xmlns` +); +function isRenderableAttrValue(value) { + if (value == null) { + return false; + } + const type = typeof value; + return type === "string" || type === "number" || type === "boolean"; +} +var cssVarNameEscapeSymbolsRE = /[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g; +function getEscapedCssVarName(key, doubleEscape) { + return key.replace( + cssVarNameEscapeSymbolsRE, + (s) => doubleEscape ? s === '"' ? '\\\\\\"' : `\\\\${s}` : `\\${s}` + ); +} +function looseCompareArrays(a, b) { + if (a.length !== b.length) return false; + let equal = true; + for (let i = 0; equal && i < a.length; i++) { + equal = looseEqual(a[i], b[i]); + } + return equal; +} +function looseEqual(a, b) { + if (a === b) return true; + let aValidType = isDate(a); + let bValidType = isDate(b); + if (aValidType || bValidType) { + return aValidType && bValidType ? a.getTime() === b.getTime() : false; + } + aValidType = isSymbol(a); + bValidType = isSymbol(b); + if (aValidType || bValidType) { + return a === b; + } + aValidType = isArray(a); + bValidType = isArray(b); + if (aValidType || bValidType) { + return aValidType && bValidType ? looseCompareArrays(a, b) : false; + } + aValidType = isObject(a); + bValidType = isObject(b); + if (aValidType || bValidType) { + if (!aValidType || !bValidType) { + return false; + } + const aKeysCount = Object.keys(a).length; + const bKeysCount = Object.keys(b).length; + if (aKeysCount !== bKeysCount) { + return false; + } + for (const key in a) { + const aHasKey = a.hasOwnProperty(key); + const bHasKey = b.hasOwnProperty(key); + if (aHasKey && !bHasKey || !aHasKey && bHasKey || !looseEqual(a[key], b[key])) { + return false; + } + } + } + return String(a) === String(b); +} +function looseIndexOf(arr, val) { + return arr.findIndex((item) => looseEqual(item, val)); +} +var isRef = (val) => { + return !!(val && val["__v_isRef"] === true); +}; +var toDisplayString = (val) => { + return isString(val) ? val : val == null ? "" : isArray(val) || isObject(val) && (val.toString === objectToString || !isFunction(val.toString)) ? isRef(val) ? toDisplayString(val.value) : JSON.stringify(val, replacer, 2) : String(val); +}; +var replacer = (_key, val) => { + if (isRef(val)) { + return replacer(_key, val.value); + } else if (isMap(val)) { + return { + [`Map(${val.size})`]: [...val.entries()].reduce( + (entries, [key, val2], i) => { + entries[stringifySymbol(key, i) + " =>"] = val2; + return entries; + }, + {} + ) + }; + } else if (isSet(val)) { + return { + [`Set(${val.size})`]: [...val.values()].map((v) => stringifySymbol(v)) + }; + } else if (isSymbol(val)) { + return stringifySymbol(val); + } else if (isObject(val) && !isArray(val) && !isPlainObject(val)) { + return String(val); + } + return val; +}; +var stringifySymbol = (v, i = "") => { + var _a; + return ( + // Symbol.description in es2019+ so we need to cast here to pass + // the lib: es2016 check + isSymbol(v) ? `Symbol(${(_a = v.description) != null ? _a : i})` : v + ); +}; +function normalizeCssVarValue(value) { + if (value == null) { + return "initial"; + } + if (typeof value === "string") { + return value === "" ? " " : value; + } + if (typeof value !== "number" || !Number.isFinite(value)) { + if (true) { + console.warn( + "[Vue warn] Invalid value used for CSS binding. Expected a string or a finite number but received:", + value + ); + } + } + return String(value); +} + +// node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js +function warn(msg, ...args) { + console.warn(`[Vue warn] ${msg}`, ...args); +} +var activeEffectScope; +var EffectScope = class { + constructor(detached = false) { + this.detached = detached; + this._active = true; + this._on = 0; + this.effects = []; + this.cleanups = []; + this._isPaused = false; + this.parent = activeEffectScope; + if (!detached && activeEffectScope) { + this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push( + this + ) - 1; + } + } + get active() { + return this._active; + } + pause() { + if (this._active) { + this._isPaused = true; + let i, l; + if (this.scopes) { + for (i = 0, l = this.scopes.length; i < l; i++) { + this.scopes[i].pause(); + } + } + for (i = 0, l = this.effects.length; i < l; i++) { + this.effects[i].pause(); + } + } + } + /** + * Resumes the effect scope, including all child scopes and effects. + */ + resume() { + if (this._active) { + if (this._isPaused) { + this._isPaused = false; + let i, l; + if (this.scopes) { + for (i = 0, l = this.scopes.length; i < l; i++) { + this.scopes[i].resume(); + } + } + for (i = 0, l = this.effects.length; i < l; i++) { + this.effects[i].resume(); + } + } + } + } + run(fn) { + if (this._active) { + const currentEffectScope = activeEffectScope; + try { + activeEffectScope = this; + return fn(); + } finally { + activeEffectScope = currentEffectScope; + } + } else if (true) { + warn(`cannot run an inactive effect scope.`); + } + } + /** + * This should only be called on non-detached scopes + * @internal + */ + on() { + if (++this._on === 1) { + this.prevScope = activeEffectScope; + activeEffectScope = this; + } + } + /** + * This should only be called on non-detached scopes + * @internal + */ + off() { + if (this._on > 0 && --this._on === 0) { + activeEffectScope = this.prevScope; + this.prevScope = void 0; + } + } + stop(fromParent) { + if (this._active) { + this._active = false; + let i, l; + for (i = 0, l = this.effects.length; i < l; i++) { + this.effects[i].stop(); + } + this.effects.length = 0; + for (i = 0, l = this.cleanups.length; i < l; i++) { + this.cleanups[i](); + } + this.cleanups.length = 0; + if (this.scopes) { + for (i = 0, l = this.scopes.length; i < l; i++) { + this.scopes[i].stop(true); + } + this.scopes.length = 0; + } + if (!this.detached && this.parent && !fromParent) { + const last = this.parent.scopes.pop(); + if (last && last !== this) { + this.parent.scopes[this.index] = last; + last.index = this.index; + } + } + this.parent = void 0; + } + } +}; +function effectScope(detached) { + return new EffectScope(detached); +} +function getCurrentScope() { + return activeEffectScope; +} +function onScopeDispose(fn, failSilently = false) { + if (activeEffectScope) { + activeEffectScope.cleanups.push(fn); + } else if (!failSilently) { + warn( + `onScopeDispose() is called when there is no active effect scope to be associated with.` + ); + } +} +var activeSub; +var pausedQueueEffects = /* @__PURE__ */ new WeakSet(); +var ReactiveEffect = class { + constructor(fn) { + this.fn = fn; + this.deps = void 0; + this.depsTail = void 0; + this.flags = 1 | 4; + this.next = void 0; + this.cleanup = void 0; + this.scheduler = void 0; + if (activeEffectScope && activeEffectScope.active) { + activeEffectScope.effects.push(this); + } + } + pause() { + this.flags |= 64; + } + resume() { + if (this.flags & 64) { + this.flags &= -65; + if (pausedQueueEffects.has(this)) { + pausedQueueEffects.delete(this); + this.trigger(); + } + } + } + /** + * @internal + */ + notify() { + if (this.flags & 2 && !(this.flags & 32)) { + return; + } + if (!(this.flags & 8)) { + batch(this); + } + } + run() { + if (!(this.flags & 1)) { + return this.fn(); + } + this.flags |= 2; + cleanupEffect(this); + prepareDeps(this); + const prevEffect = activeSub; + const prevShouldTrack = shouldTrack; + activeSub = this; + shouldTrack = true; + try { + return this.fn(); + } finally { + if (activeSub !== this) { + warn( + "Active effect was not restored correctly - this is likely a Vue internal bug." + ); + } + cleanupDeps(this); + activeSub = prevEffect; + shouldTrack = prevShouldTrack; + this.flags &= -3; + } + } + stop() { + if (this.flags & 1) { + for (let link = this.deps; link; link = link.nextDep) { + removeSub(link); + } + this.deps = this.depsTail = void 0; + cleanupEffect(this); + this.onStop && this.onStop(); + this.flags &= -2; + } + } + trigger() { + if (this.flags & 64) { + pausedQueueEffects.add(this); + } else if (this.scheduler) { + this.scheduler(); + } else { + this.runIfDirty(); + } + } + /** + * @internal + */ + runIfDirty() { + if (isDirty(this)) { + this.run(); + } + } + get dirty() { + return isDirty(this); + } +}; +var batchDepth = 0; +var batchedSub; +var batchedComputed; +function batch(sub, isComputed = false) { + sub.flags |= 8; + if (isComputed) { + sub.next = batchedComputed; + batchedComputed = sub; + return; + } + sub.next = batchedSub; + batchedSub = sub; +} +function startBatch() { + batchDepth++; +} +function endBatch() { + if (--batchDepth > 0) { + return; + } + if (batchedComputed) { + let e = batchedComputed; + batchedComputed = void 0; + while (e) { + const next = e.next; + e.next = void 0; + e.flags &= -9; + e = next; + } + } + let error; + while (batchedSub) { + let e = batchedSub; + batchedSub = void 0; + while (e) { + const next = e.next; + e.next = void 0; + e.flags &= -9; + if (e.flags & 1) { + try { + ; + e.trigger(); + } catch (err) { + if (!error) error = err; + } + } + e = next; + } + } + if (error) throw error; +} +function prepareDeps(sub) { + for (let link = sub.deps; link; link = link.nextDep) { + link.version = -1; + link.prevActiveLink = link.dep.activeLink; + link.dep.activeLink = link; + } +} +function cleanupDeps(sub) { + let head; + let tail = sub.depsTail; + let link = tail; + while (link) { + const prev = link.prevDep; + if (link.version === -1) { + if (link === tail) tail = prev; + removeSub(link); + removeDep(link); + } else { + head = link; + } + link.dep.activeLink = link.prevActiveLink; + link.prevActiveLink = void 0; + link = prev; + } + sub.deps = head; + sub.depsTail = tail; +} +function isDirty(sub) { + for (let link = sub.deps; link; link = link.nextDep) { + if (link.dep.version !== link.version || link.dep.computed && (refreshComputed(link.dep.computed) || link.dep.version !== link.version)) { + return true; + } + } + if (sub._dirty) { + return true; + } + return false; +} +function refreshComputed(computed3) { + if (computed3.flags & 4 && !(computed3.flags & 16)) { + return; + } + computed3.flags &= -17; + if (computed3.globalVersion === globalVersion) { + return; + } + computed3.globalVersion = globalVersion; + if (!computed3.isSSR && computed3.flags & 128 && (!computed3.deps && !computed3._dirty || !isDirty(computed3))) { + return; + } + computed3.flags |= 2; + const dep = computed3.dep; + const prevSub = activeSub; + const prevShouldTrack = shouldTrack; + activeSub = computed3; + shouldTrack = true; + try { + prepareDeps(computed3); + const value = computed3.fn(computed3._value); + if (dep.version === 0 || hasChanged(value, computed3._value)) { + computed3.flags |= 128; + computed3._value = value; + dep.version++; + } + } catch (err) { + dep.version++; + throw err; + } finally { + activeSub = prevSub; + shouldTrack = prevShouldTrack; + cleanupDeps(computed3); + computed3.flags &= -3; + } +} +function removeSub(link, soft = false) { + const { dep, prevSub, nextSub } = link; + if (prevSub) { + prevSub.nextSub = nextSub; + link.prevSub = void 0; + } + if (nextSub) { + nextSub.prevSub = prevSub; + link.nextSub = void 0; + } + if (dep.subsHead === link) { + dep.subsHead = nextSub; + } + if (dep.subs === link) { + dep.subs = prevSub; + if (!prevSub && dep.computed) { + dep.computed.flags &= -5; + for (let l = dep.computed.deps; l; l = l.nextDep) { + removeSub(l, true); + } + } + } + if (!soft && !--dep.sc && dep.map) { + dep.map.delete(dep.key); + } +} +function removeDep(link) { + const { prevDep, nextDep } = link; + if (prevDep) { + prevDep.nextDep = nextDep; + link.prevDep = void 0; + } + if (nextDep) { + nextDep.prevDep = prevDep; + link.nextDep = void 0; + } +} +function effect(fn, options) { + if (fn.effect instanceof ReactiveEffect) { + fn = fn.effect.fn; + } + const e = new ReactiveEffect(fn); + if (options) { + extend(e, options); + } + try { + e.run(); + } catch (err) { + e.stop(); + throw err; + } + const runner = e.run.bind(e); + runner.effect = e; + return runner; +} +function stop(runner) { + runner.effect.stop(); +} +var shouldTrack = true; +var trackStack = []; +function pauseTracking() { + trackStack.push(shouldTrack); + shouldTrack = false; +} +function resetTracking() { + const last = trackStack.pop(); + shouldTrack = last === void 0 ? true : last; +} +function cleanupEffect(e) { + const { cleanup } = e; + e.cleanup = void 0; + if (cleanup) { + const prevSub = activeSub; + activeSub = void 0; + try { + cleanup(); + } finally { + activeSub = prevSub; + } + } +} +var globalVersion = 0; +var Link = class { + constructor(sub, dep) { + this.sub = sub; + this.dep = dep; + this.version = dep.version; + this.nextDep = this.prevDep = this.nextSub = this.prevSub = this.prevActiveLink = void 0; + } +}; +var Dep = class { + // TODO isolatedDeclarations "__v_skip" + constructor(computed3) { + this.computed = computed3; + this.version = 0; + this.activeLink = void 0; + this.subs = void 0; + this.map = void 0; + this.key = void 0; + this.sc = 0; + this.__v_skip = true; + if (true) { + this.subsHead = void 0; + } + } + track(debugInfo) { + if (!activeSub || !shouldTrack || activeSub === this.computed) { + return; + } + let link = this.activeLink; + if (link === void 0 || link.sub !== activeSub) { + link = this.activeLink = new Link(activeSub, this); + if (!activeSub.deps) { + activeSub.deps = activeSub.depsTail = link; + } else { + link.prevDep = activeSub.depsTail; + activeSub.depsTail.nextDep = link; + activeSub.depsTail = link; + } + addSub(link); + } else if (link.version === -1) { + link.version = this.version; + if (link.nextDep) { + const next = link.nextDep; + next.prevDep = link.prevDep; + if (link.prevDep) { + link.prevDep.nextDep = next; + } + link.prevDep = activeSub.depsTail; + link.nextDep = void 0; + activeSub.depsTail.nextDep = link; + activeSub.depsTail = link; + if (activeSub.deps === link) { + activeSub.deps = next; + } + } + } + if (activeSub.onTrack) { + activeSub.onTrack( + extend( + { + effect: activeSub + }, + debugInfo + ) + ); + } + return link; + } + trigger(debugInfo) { + this.version++; + globalVersion++; + this.notify(debugInfo); + } + notify(debugInfo) { + startBatch(); + try { + if (true) { + for (let head = this.subsHead; head; head = head.nextSub) { + if (head.sub.onTrigger && !(head.sub.flags & 8)) { + head.sub.onTrigger( + extend( + { + effect: head.sub + }, + debugInfo + ) + ); + } + } + } + for (let link = this.subs; link; link = link.prevSub) { + if (link.sub.notify()) { + ; + link.sub.dep.notify(); + } + } + } finally { + endBatch(); + } + } +}; +function addSub(link) { + link.dep.sc++; + if (link.sub.flags & 4) { + const computed3 = link.dep.computed; + if (computed3 && !link.dep.subs) { + computed3.flags |= 4 | 16; + for (let l = computed3.deps; l; l = l.nextDep) { + addSub(l); + } + } + const currentTail = link.dep.subs; + if (currentTail !== link) { + link.prevSub = currentTail; + if (currentTail) currentTail.nextSub = link; + } + if (link.dep.subsHead === void 0) { + link.dep.subsHead = link; + } + link.dep.subs = link; + } +} +var targetMap = /* @__PURE__ */ new WeakMap(); +var ITERATE_KEY = Symbol( + true ? "Object iterate" : "" +); +var MAP_KEY_ITERATE_KEY = Symbol( + true ? "Map keys iterate" : "" +); +var ARRAY_ITERATE_KEY = Symbol( + true ? "Array iterate" : "" +); +function track(target, type, key) { + if (shouldTrack && activeSub) { + let depsMap = targetMap.get(target); + if (!depsMap) { + targetMap.set(target, depsMap = /* @__PURE__ */ new Map()); + } + let dep = depsMap.get(key); + if (!dep) { + depsMap.set(key, dep = new Dep()); + dep.map = depsMap; + dep.key = key; + } + if (true) { + dep.track({ + target, + type, + key + }); + } else { + dep.track(); + } + } +} +function trigger(target, type, key, newValue, oldValue, oldTarget) { + const depsMap = targetMap.get(target); + if (!depsMap) { + globalVersion++; + return; + } + const run = (dep) => { + if (dep) { + if (true) { + dep.trigger({ + target, + type, + key, + newValue, + oldValue, + oldTarget + }); + } else { + dep.trigger(); + } + } + }; + startBatch(); + if (type === "clear") { + depsMap.forEach(run); + } else { + const targetIsArray = isArray(target); + const isArrayIndex = targetIsArray && isIntegerKey(key); + if (targetIsArray && key === "length") { + const newLength = Number(newValue); + depsMap.forEach((dep, key2) => { + if (key2 === "length" || key2 === ARRAY_ITERATE_KEY || !isSymbol(key2) && key2 >= newLength) { + run(dep); + } + }); + } else { + if (key !== void 0 || depsMap.has(void 0)) { + run(depsMap.get(key)); + } + if (isArrayIndex) { + run(depsMap.get(ARRAY_ITERATE_KEY)); + } + switch (type) { + case "add": + if (!targetIsArray) { + run(depsMap.get(ITERATE_KEY)); + if (isMap(target)) { + run(depsMap.get(MAP_KEY_ITERATE_KEY)); + } + } else if (isArrayIndex) { + run(depsMap.get("length")); + } + break; + case "delete": + if (!targetIsArray) { + run(depsMap.get(ITERATE_KEY)); + if (isMap(target)) { + run(depsMap.get(MAP_KEY_ITERATE_KEY)); + } + } + break; + case "set": + if (isMap(target)) { + run(depsMap.get(ITERATE_KEY)); + } + break; + } + } + } + endBatch(); +} +function getDepFromReactive(object, key) { + const depMap = targetMap.get(object); + return depMap && depMap.get(key); +} +function reactiveReadArray(array) { + const raw = toRaw(array); + if (raw === array) return raw; + track(raw, "iterate", ARRAY_ITERATE_KEY); + return isShallow(array) ? raw : raw.map(toReactive); +} +function shallowReadArray(arr) { + track(arr = toRaw(arr), "iterate", ARRAY_ITERATE_KEY); + return arr; +} +function toWrapped(target, item) { + if (isReadonly(target)) { + return isReactive(target) ? toReadonly(toReactive(item)) : toReadonly(item); + } + return toReactive(item); +} +var arrayInstrumentations = { + __proto__: null, + [Symbol.iterator]() { + return iterator(this, Symbol.iterator, (item) => toWrapped(this, item)); + }, + concat(...args) { + return reactiveReadArray(this).concat( + ...args.map((x) => isArray(x) ? reactiveReadArray(x) : x) + ); + }, + entries() { + return iterator(this, "entries", (value) => { + value[1] = toWrapped(this, value[1]); + return value; + }); + }, + every(fn, thisArg) { + return apply(this, "every", fn, thisArg, void 0, arguments); + }, + filter(fn, thisArg) { + return apply( + this, + "filter", + fn, + thisArg, + (v) => v.map((item) => toWrapped(this, item)), + arguments + ); + }, + find(fn, thisArg) { + return apply( + this, + "find", + fn, + thisArg, + (item) => toWrapped(this, item), + arguments + ); + }, + findIndex(fn, thisArg) { + return apply(this, "findIndex", fn, thisArg, void 0, arguments); + }, + findLast(fn, thisArg) { + return apply( + this, + "findLast", + fn, + thisArg, + (item) => toWrapped(this, item), + arguments + ); + }, + findLastIndex(fn, thisArg) { + return apply(this, "findLastIndex", fn, thisArg, void 0, arguments); + }, + // flat, flatMap could benefit from ARRAY_ITERATE but are not straight-forward to implement + forEach(fn, thisArg) { + return apply(this, "forEach", fn, thisArg, void 0, arguments); + }, + includes(...args) { + return searchProxy(this, "includes", args); + }, + indexOf(...args) { + return searchProxy(this, "indexOf", args); + }, + join(separator) { + return reactiveReadArray(this).join(separator); + }, + // keys() iterator only reads `length`, no optimization required + lastIndexOf(...args) { + return searchProxy(this, "lastIndexOf", args); + }, + map(fn, thisArg) { + return apply(this, "map", fn, thisArg, void 0, arguments); + }, + pop() { + return noTracking(this, "pop"); + }, + push(...args) { + return noTracking(this, "push", args); + }, + reduce(fn, ...args) { + return reduce(this, "reduce", fn, args); + }, + reduceRight(fn, ...args) { + return reduce(this, "reduceRight", fn, args); + }, + shift() { + return noTracking(this, "shift"); + }, + // slice could use ARRAY_ITERATE but also seems to beg for range tracking + some(fn, thisArg) { + return apply(this, "some", fn, thisArg, void 0, arguments); + }, + splice(...args) { + return noTracking(this, "splice", args); + }, + toReversed() { + return reactiveReadArray(this).toReversed(); + }, + toSorted(comparer) { + return reactiveReadArray(this).toSorted(comparer); + }, + toSpliced(...args) { + return reactiveReadArray(this).toSpliced(...args); + }, + unshift(...args) { + return noTracking(this, "unshift", args); + }, + values() { + return iterator(this, "values", (item) => toWrapped(this, item)); + } +}; +function iterator(self2, method, wrapValue) { + const arr = shallowReadArray(self2); + const iter = arr[method](); + if (arr !== self2 && !isShallow(self2)) { + iter._next = iter.next; + iter.next = () => { + const result = iter._next(); + if (!result.done) { + result.value = wrapValue(result.value); + } + return result; + }; + } + return iter; +} +var arrayProto = Array.prototype; +function apply(self2, method, fn, thisArg, wrappedRetFn, args) { + const arr = shallowReadArray(self2); + const needsWrap = arr !== self2 && !isShallow(self2); + const methodFn = arr[method]; + if (methodFn !== arrayProto[method]) { + const result2 = methodFn.apply(self2, args); + return needsWrap ? toReactive(result2) : result2; + } + let wrappedFn = fn; + if (arr !== self2) { + if (needsWrap) { + wrappedFn = function(item, index) { + return fn.call(this, toWrapped(self2, item), index, self2); + }; + } else if (fn.length > 2) { + wrappedFn = function(item, index) { + return fn.call(this, item, index, self2); + }; + } + } + const result = methodFn.call(arr, wrappedFn, thisArg); + return needsWrap && wrappedRetFn ? wrappedRetFn(result) : result; +} +function reduce(self2, method, fn, args) { + const arr = shallowReadArray(self2); + let wrappedFn = fn; + if (arr !== self2) { + if (!isShallow(self2)) { + wrappedFn = function(acc, item, index) { + return fn.call(this, acc, toWrapped(self2, item), index, self2); + }; + } else if (fn.length > 3) { + wrappedFn = function(acc, item, index) { + return fn.call(this, acc, item, index, self2); + }; + } + } + return arr[method](wrappedFn, ...args); +} +function searchProxy(self2, method, args) { + const arr = toRaw(self2); + track(arr, "iterate", ARRAY_ITERATE_KEY); + const res = arr[method](...args); + if ((res === -1 || res === false) && isProxy(args[0])) { + args[0] = toRaw(args[0]); + return arr[method](...args); + } + return res; +} +function noTracking(self2, method, args = []) { + pauseTracking(); + startBatch(); + const res = toRaw(self2)[method].apply(self2, args); + endBatch(); + resetTracking(); + return res; +} +var isNonTrackableKeys = makeMap(`__proto__,__v_isRef,__isVue`); +var builtInSymbols = new Set( + Object.getOwnPropertyNames(Symbol).filter((key) => key !== "arguments" && key !== "caller").map((key) => Symbol[key]).filter(isSymbol) +); +function hasOwnProperty2(key) { + if (!isSymbol(key)) key = String(key); + const obj = toRaw(this); + track(obj, "has", key); + return obj.hasOwnProperty(key); +} +var BaseReactiveHandler = class { + constructor(_isReadonly = false, _isShallow = false) { + this._isReadonly = _isReadonly; + this._isShallow = _isShallow; + } + get(target, key, receiver) { + if (key === "__v_skip") return target["__v_skip"]; + const isReadonly2 = this._isReadonly, isShallow2 = this._isShallow; + if (key === "__v_isReactive") { + return !isReadonly2; + } else if (key === "__v_isReadonly") { + return isReadonly2; + } else if (key === "__v_isShallow") { + return isShallow2; + } else if (key === "__v_raw") { + if (receiver === (isReadonly2 ? isShallow2 ? shallowReadonlyMap : readonlyMap : isShallow2 ? shallowReactiveMap : reactiveMap).get(target) || // receiver is not the reactive proxy, but has the same prototype + // this means the receiver is a user proxy of the reactive proxy + Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)) { + return target; + } + return; + } + const targetIsArray = isArray(target); + if (!isReadonly2) { + let fn; + if (targetIsArray && (fn = arrayInstrumentations[key])) { + return fn; + } + if (key === "hasOwnProperty") { + return hasOwnProperty2; + } + } + const res = Reflect.get( + target, + key, + // if this is a proxy wrapping a ref, return methods using the raw ref + // as receiver so that we don't have to call `toRaw` on the ref in all + // its class methods + isRef2(target) ? target : receiver + ); + if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) { + return res; + } + if (!isReadonly2) { + track(target, "get", key); + } + if (isShallow2) { + return res; + } + if (isRef2(res)) { + const value = targetIsArray && isIntegerKey(key) ? res : res.value; + return isReadonly2 && isObject(value) ? readonly(value) : value; + } + if (isObject(res)) { + return isReadonly2 ? readonly(res) : reactive(res); + } + return res; + } +}; +var MutableReactiveHandler = class extends BaseReactiveHandler { + constructor(isShallow2 = false) { + super(false, isShallow2); + } + set(target, key, value, receiver) { + let oldValue = target[key]; + const isArrayWithIntegerKey = isArray(target) && isIntegerKey(key); + if (!this._isShallow) { + const isOldValueReadonly = isReadonly(oldValue); + if (!isShallow(value) && !isReadonly(value)) { + oldValue = toRaw(oldValue); + value = toRaw(value); + } + if (!isArrayWithIntegerKey && isRef2(oldValue) && !isRef2(value)) { + if (isOldValueReadonly) { + if (true) { + warn( + `Set operation on key "${String(key)}" failed: target is readonly.`, + target[key] + ); + } + return true; + } else { + oldValue.value = value; + return true; + } + } + } + const hadKey = isArrayWithIntegerKey ? Number(key) < target.length : hasOwn(target, key); + const result = Reflect.set( + target, + key, + value, + isRef2(target) ? target : receiver + ); + if (target === toRaw(receiver)) { + if (!hadKey) { + trigger(target, "add", key, value); + } else if (hasChanged(value, oldValue)) { + trigger(target, "set", key, value, oldValue); + } + } + return result; + } + deleteProperty(target, key) { + const hadKey = hasOwn(target, key); + const oldValue = target[key]; + const result = Reflect.deleteProperty(target, key); + if (result && hadKey) { + trigger(target, "delete", key, void 0, oldValue); + } + return result; + } + has(target, key) { + const result = Reflect.has(target, key); + if (!isSymbol(key) || !builtInSymbols.has(key)) { + track(target, "has", key); + } + return result; + } + ownKeys(target) { + track( + target, + "iterate", + isArray(target) ? "length" : ITERATE_KEY + ); + return Reflect.ownKeys(target); + } +}; +var ReadonlyReactiveHandler = class extends BaseReactiveHandler { + constructor(isShallow2 = false) { + super(true, isShallow2); + } + set(target, key) { + if (true) { + warn( + `Set operation on key "${String(key)}" failed: target is readonly.`, + target + ); + } + return true; + } + deleteProperty(target, key) { + if (true) { + warn( + `Delete operation on key "${String(key)}" failed: target is readonly.`, + target + ); + } + return true; + } +}; +var mutableHandlers = new MutableReactiveHandler(); +var readonlyHandlers = new ReadonlyReactiveHandler(); +var shallowReactiveHandlers = new MutableReactiveHandler(true); +var shallowReadonlyHandlers = new ReadonlyReactiveHandler(true); +var toShallow = (value) => value; +var getProto = (v) => Reflect.getPrototypeOf(v); +function createIterableMethod(method, isReadonly2, isShallow2) { + return function(...args) { + const target = this["__v_raw"]; + const rawTarget = toRaw(target); + const targetIsMap = isMap(rawTarget); + const isPair = method === "entries" || method === Symbol.iterator && targetIsMap; + const isKeyOnly = method === "keys" && targetIsMap; + const innerIterator = target[method](...args); + const wrap = isShallow2 ? toShallow : isReadonly2 ? toReadonly : toReactive; + !isReadonly2 && track( + rawTarget, + "iterate", + isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY + ); + return { + // iterator protocol + next() { + const { value, done } = innerIterator.next(); + return done ? { value, done } : { + value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value), + done + }; + }, + // iterable protocol + [Symbol.iterator]() { + return this; + } + }; + }; +} +function createReadonlyMethod(type) { + return function(...args) { + if (true) { + const key = args[0] ? `on key "${args[0]}" ` : ``; + warn( + `${capitalize(type)} operation ${key}failed: target is readonly.`, + toRaw(this) + ); + } + return type === "delete" ? false : type === "clear" ? void 0 : this; + }; +} +function createInstrumentations(readonly2, shallow) { + const instrumentations = { + get(key) { + const target = this["__v_raw"]; + const rawTarget = toRaw(target); + const rawKey = toRaw(key); + if (!readonly2) { + if (hasChanged(key, rawKey)) { + track(rawTarget, "get", key); + } + track(rawTarget, "get", rawKey); + } + const { has } = getProto(rawTarget); + const wrap = shallow ? toShallow : readonly2 ? toReadonly : toReactive; + if (has.call(rawTarget, key)) { + return wrap(target.get(key)); + } else if (has.call(rawTarget, rawKey)) { + return wrap(target.get(rawKey)); + } else if (target !== rawTarget) { + target.get(key); + } + }, + get size() { + const target = this["__v_raw"]; + !readonly2 && track(toRaw(target), "iterate", ITERATE_KEY); + return target.size; + }, + has(key) { + const target = this["__v_raw"]; + const rawTarget = toRaw(target); + const rawKey = toRaw(key); + if (!readonly2) { + if (hasChanged(key, rawKey)) { + track(rawTarget, "has", key); + } + track(rawTarget, "has", rawKey); + } + return key === rawKey ? target.has(key) : target.has(key) || target.has(rawKey); + }, + forEach(callback, thisArg) { + const observed = this; + const target = observed["__v_raw"]; + const rawTarget = toRaw(target); + const wrap = shallow ? toShallow : readonly2 ? toReadonly : toReactive; + !readonly2 && track(rawTarget, "iterate", ITERATE_KEY); + return target.forEach((value, key) => { + return callback.call(thisArg, wrap(value), wrap(key), observed); + }); + } + }; + extend( + instrumentations, + readonly2 ? { + add: createReadonlyMethod("add"), + set: createReadonlyMethod("set"), + delete: createReadonlyMethod("delete"), + clear: createReadonlyMethod("clear") + } : { + add(value) { + if (!shallow && !isShallow(value) && !isReadonly(value)) { + value = toRaw(value); + } + const target = toRaw(this); + const proto = getProto(target); + const hadKey = proto.has.call(target, value); + if (!hadKey) { + target.add(value); + trigger(target, "add", value, value); + } + return this; + }, + set(key, value) { + if (!shallow && !isShallow(value) && !isReadonly(value)) { + value = toRaw(value); + } + const target = toRaw(this); + const { has, get } = getProto(target); + let hadKey = has.call(target, key); + if (!hadKey) { + key = toRaw(key); + hadKey = has.call(target, key); + } else if (true) { + checkIdentityKeys(target, has, key); + } + const oldValue = get.call(target, key); + target.set(key, value); + if (!hadKey) { + trigger(target, "add", key, value); + } else if (hasChanged(value, oldValue)) { + trigger(target, "set", key, value, oldValue); + } + return this; + }, + delete(key) { + const target = toRaw(this); + const { has, get } = getProto(target); + let hadKey = has.call(target, key); + if (!hadKey) { + key = toRaw(key); + hadKey = has.call(target, key); + } else if (true) { + checkIdentityKeys(target, has, key); + } + const oldValue = get ? get.call(target, key) : void 0; + const result = target.delete(key); + if (hadKey) { + trigger(target, "delete", key, void 0, oldValue); + } + return result; + }, + clear() { + const target = toRaw(this); + const hadItems = target.size !== 0; + const oldTarget = true ? isMap(target) ? new Map(target) : new Set(target) : void 0; + const result = target.clear(); + if (hadItems) { + trigger( + target, + "clear", + void 0, + void 0, + oldTarget + ); + } + return result; + } + } + ); + const iteratorMethods = [ + "keys", + "values", + "entries", + Symbol.iterator + ]; + iteratorMethods.forEach((method) => { + instrumentations[method] = createIterableMethod(method, readonly2, shallow); + }); + return instrumentations; +} +function createInstrumentationGetter(isReadonly2, shallow) { + const instrumentations = createInstrumentations(isReadonly2, shallow); + return (target, key, receiver) => { + if (key === "__v_isReactive") { + return !isReadonly2; + } else if (key === "__v_isReadonly") { + return isReadonly2; + } else if (key === "__v_raw") { + return target; + } + return Reflect.get( + hasOwn(instrumentations, key) && key in target ? instrumentations : target, + key, + receiver + ); + }; +} +var mutableCollectionHandlers = { + get: createInstrumentationGetter(false, false) +}; +var shallowCollectionHandlers = { + get: createInstrumentationGetter(false, true) +}; +var readonlyCollectionHandlers = { + get: createInstrumentationGetter(true, false) +}; +var shallowReadonlyCollectionHandlers = { + get: createInstrumentationGetter(true, true) +}; +function checkIdentityKeys(target, has, key) { + const rawKey = toRaw(key); + if (rawKey !== key && has.call(target, rawKey)) { + const type = toRawType(target); + warn( + `Reactive ${type} contains both the raw and reactive versions of the same object${type === `Map` ? ` as keys` : ``}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.` + ); + } +} +var reactiveMap = /* @__PURE__ */ new WeakMap(); +var shallowReactiveMap = /* @__PURE__ */ new WeakMap(); +var readonlyMap = /* @__PURE__ */ new WeakMap(); +var shallowReadonlyMap = /* @__PURE__ */ new WeakMap(); +function targetTypeMap(rawType) { + switch (rawType) { + case "Object": + case "Array": + return 1; + case "Map": + case "Set": + case "WeakMap": + case "WeakSet": + return 2; + default: + return 0; + } +} +function getTargetType(value) { + return value["__v_skip"] || !Object.isExtensible(value) ? 0 : targetTypeMap(toRawType(value)); +} +function reactive(target) { + if (isReadonly(target)) { + return target; + } + return createReactiveObject( + target, + false, + mutableHandlers, + mutableCollectionHandlers, + reactiveMap + ); +} +function shallowReactive(target) { + return createReactiveObject( + target, + false, + shallowReactiveHandlers, + shallowCollectionHandlers, + shallowReactiveMap + ); +} +function readonly(target) { + return createReactiveObject( + target, + true, + readonlyHandlers, + readonlyCollectionHandlers, + readonlyMap + ); +} +function shallowReadonly(target) { + return createReactiveObject( + target, + true, + shallowReadonlyHandlers, + shallowReadonlyCollectionHandlers, + shallowReadonlyMap + ); +} +function createReactiveObject(target, isReadonly2, baseHandlers, collectionHandlers, proxyMap) { + if (!isObject(target)) { + if (true) { + warn( + `value cannot be made ${isReadonly2 ? "readonly" : "reactive"}: ${String( + target + )}` + ); + } + return target; + } + if (target["__v_raw"] && !(isReadonly2 && target["__v_isReactive"])) { + return target; + } + const targetType = getTargetType(target); + if (targetType === 0) { + return target; + } + const existingProxy = proxyMap.get(target); + if (existingProxy) { + return existingProxy; + } + const proxy = new Proxy( + target, + targetType === 2 ? collectionHandlers : baseHandlers + ); + proxyMap.set(target, proxy); + return proxy; +} +function isReactive(value) { + if (isReadonly(value)) { + return isReactive(value["__v_raw"]); + } + return !!(value && value["__v_isReactive"]); +} +function isReadonly(value) { + return !!(value && value["__v_isReadonly"]); +} +function isShallow(value) { + return !!(value && value["__v_isShallow"]); +} +function isProxy(value) { + return value ? !!value["__v_raw"] : false; +} +function toRaw(observed) { + const raw = observed && observed["__v_raw"]; + return raw ? toRaw(raw) : observed; +} +function markRaw(value) { + if (!hasOwn(value, "__v_skip") && Object.isExtensible(value)) { + def(value, "__v_skip", true); + } + return value; +} +var toReactive = (value) => isObject(value) ? reactive(value) : value; +var toReadonly = (value) => isObject(value) ? readonly(value) : value; +function isRef2(r) { + return r ? r["__v_isRef"] === true : false; +} +function ref(value) { + return createRef(value, false); +} +function shallowRef(value) { + return createRef(value, true); +} +function createRef(rawValue, shallow) { + if (isRef2(rawValue)) { + return rawValue; + } + return new RefImpl(rawValue, shallow); +} +var RefImpl = class { + constructor(value, isShallow2) { + this.dep = new Dep(); + this["__v_isRef"] = true; + this["__v_isShallow"] = false; + this._rawValue = isShallow2 ? value : toRaw(value); + this._value = isShallow2 ? value : toReactive(value); + this["__v_isShallow"] = isShallow2; + } + get value() { + if (true) { + this.dep.track({ + target: this, + type: "get", + key: "value" + }); + } else { + this.dep.track(); + } + return this._value; + } + set value(newValue) { + const oldValue = this._rawValue; + const useDirectValue = this["__v_isShallow"] || isShallow(newValue) || isReadonly(newValue); + newValue = useDirectValue ? newValue : toRaw(newValue); + if (hasChanged(newValue, oldValue)) { + this._rawValue = newValue; + this._value = useDirectValue ? newValue : toReactive(newValue); + if (true) { + this.dep.trigger({ + target: this, + type: "set", + key: "value", + newValue, + oldValue + }); + } else { + this.dep.trigger(); + } + } + } +}; +function triggerRef(ref2) { + if (ref2.dep) { + if (true) { + ref2.dep.trigger({ + target: ref2, + type: "set", + key: "value", + newValue: ref2._value + }); + } else { + ref2.dep.trigger(); + } + } +} +function unref(ref2) { + return isRef2(ref2) ? ref2.value : ref2; +} +function toValue(source) { + return isFunction(source) ? source() : unref(source); +} +var shallowUnwrapHandlers = { + get: (target, key, receiver) => key === "__v_raw" ? target : unref(Reflect.get(target, key, receiver)), + set: (target, key, value, receiver) => { + const oldValue = target[key]; + if (isRef2(oldValue) && !isRef2(value)) { + oldValue.value = value; + return true; + } else { + return Reflect.set(target, key, value, receiver); + } + } +}; +function proxyRefs(objectWithRefs) { + return isReactive(objectWithRefs) ? objectWithRefs : new Proxy(objectWithRefs, shallowUnwrapHandlers); +} +var CustomRefImpl = class { + constructor(factory) { + this["__v_isRef"] = true; + this._value = void 0; + const dep = this.dep = new Dep(); + const { get, set } = factory(dep.track.bind(dep), dep.trigger.bind(dep)); + this._get = get; + this._set = set; + } + get value() { + return this._value = this._get(); + } + set value(newVal) { + this._set(newVal); + } +}; +function customRef(factory) { + return new CustomRefImpl(factory); +} +function toRefs(object) { + if (!isProxy(object)) { + warn(`toRefs() expects a reactive object but received a plain one.`); + } + const ret = isArray(object) ? new Array(object.length) : {}; + for (const key in object) { + ret[key] = propertyToRef(object, key); + } + return ret; +} +var ObjectRefImpl = class { + constructor(_object, _key, _defaultValue) { + this._object = _object; + this._key = _key; + this._defaultValue = _defaultValue; + this["__v_isRef"] = true; + this._value = void 0; + this._raw = toRaw(_object); + let shallow = true; + let obj = _object; + if (!isArray(_object) || !isIntegerKey(String(_key))) { + do { + shallow = !isProxy(obj) || isShallow(obj); + } while (shallow && (obj = obj["__v_raw"])); + } + this._shallow = shallow; + } + get value() { + let val = this._object[this._key]; + if (this._shallow) { + val = unref(val); + } + return this._value = val === void 0 ? this._defaultValue : val; + } + set value(newVal) { + if (this._shallow && isRef2(this._raw[this._key])) { + const nestedRef = this._object[this._key]; + if (isRef2(nestedRef)) { + nestedRef.value = newVal; + return; + } + } + this._object[this._key] = newVal; + } + get dep() { + return getDepFromReactive(this._raw, this._key); + } +}; +var GetterRefImpl = class { + constructor(_getter) { + this._getter = _getter; + this["__v_isRef"] = true; + this["__v_isReadonly"] = true; + this._value = void 0; + } + get value() { + return this._value = this._getter(); + } +}; +function toRef(source, key, defaultValue) { + if (isRef2(source)) { + return source; + } else if (isFunction(source)) { + return new GetterRefImpl(source); + } else if (isObject(source) && arguments.length > 1) { + return propertyToRef(source, key, defaultValue); + } else { + return ref(source); + } +} +function propertyToRef(source, key, defaultValue) { + return new ObjectRefImpl(source, key, defaultValue); +} +var ComputedRefImpl = class { + constructor(fn, setter, isSSR) { + this.fn = fn; + this.setter = setter; + this._value = void 0; + this.dep = new Dep(this); + this.__v_isRef = true; + this.deps = void 0; + this.depsTail = void 0; + this.flags = 16; + this.globalVersion = globalVersion - 1; + this.next = void 0; + this.effect = this; + this["__v_isReadonly"] = !setter; + this.isSSR = isSSR; + } + /** + * @internal + */ + notify() { + this.flags |= 16; + if (!(this.flags & 8) && // avoid infinite self recursion + activeSub !== this) { + batch(this, true); + return true; + } else if (true) ; + } + get value() { + const link = true ? this.dep.track({ + target: this, + type: "get", + key: "value" + }) : this.dep.track(); + refreshComputed(this); + if (link) { + link.version = this.dep.version; + } + return this._value; + } + set value(newValue) { + if (this.setter) { + this.setter(newValue); + } else if (true) { + warn("Write operation failed: computed value is readonly"); + } + } +}; +function computed(getterOrOptions, debugOptions, isSSR = false) { + let getter; + let setter; + if (isFunction(getterOrOptions)) { + getter = getterOrOptions; + } else { + getter = getterOrOptions.get; + setter = getterOrOptions.set; + } + const cRef = new ComputedRefImpl(getter, setter, isSSR); + if (debugOptions && !isSSR) { + cRef.onTrack = debugOptions.onTrack; + cRef.onTrigger = debugOptions.onTrigger; + } + return cRef; +} +var TrackOpTypes = { + "GET": "get", + "HAS": "has", + "ITERATE": "iterate" +}; +var TriggerOpTypes = { + "SET": "set", + "ADD": "add", + "DELETE": "delete", + "CLEAR": "clear" +}; +var INITIAL_WATCHER_VALUE = {}; +var cleanupMap = /* @__PURE__ */ new WeakMap(); +var activeWatcher = void 0; +function getCurrentWatcher() { + return activeWatcher; +} +function onWatcherCleanup(cleanupFn, failSilently = false, owner = activeWatcher) { + if (owner) { + let cleanups = cleanupMap.get(owner); + if (!cleanups) cleanupMap.set(owner, cleanups = []); + cleanups.push(cleanupFn); + } else if (!failSilently) { + warn( + `onWatcherCleanup() was called when there was no active watcher to associate with.` + ); + } +} +function watch(source, cb, options = EMPTY_OBJ) { + const { immediate, deep, once, scheduler, augmentJob, call } = options; + const warnInvalidSource = (s) => { + (options.onWarn || warn)( + `Invalid watch source: `, + s, + `A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types.` + ); + }; + const reactiveGetter = (source2) => { + if (deep) return source2; + if (isShallow(source2) || deep === false || deep === 0) + return traverse(source2, 1); + return traverse(source2); + }; + let effect2; + let getter; + let cleanup; + let boundCleanup; + let forceTrigger = false; + let isMultiSource = false; + if (isRef2(source)) { + getter = () => source.value; + forceTrigger = isShallow(source); + } else if (isReactive(source)) { + getter = () => reactiveGetter(source); + forceTrigger = true; + } else if (isArray(source)) { + isMultiSource = true; + forceTrigger = source.some((s) => isReactive(s) || isShallow(s)); + getter = () => source.map((s) => { + if (isRef2(s)) { + return s.value; + } else if (isReactive(s)) { + return reactiveGetter(s); + } else if (isFunction(s)) { + return call ? call(s, 2) : s(); + } else { + warnInvalidSource(s); + } + }); + } else if (isFunction(source)) { + if (cb) { + getter = call ? () => call(source, 2) : source; + } else { + getter = () => { + if (cleanup) { + pauseTracking(); + try { + cleanup(); + } finally { + resetTracking(); + } + } + const currentEffect = activeWatcher; + activeWatcher = effect2; + try { + return call ? call(source, 3, [boundCleanup]) : source(boundCleanup); + } finally { + activeWatcher = currentEffect; + } + }; + } + } else { + getter = NOOP; + warnInvalidSource(source); + } + if (cb && deep) { + const baseGetter = getter; + const depth = deep === true ? Infinity : deep; + getter = () => traverse(baseGetter(), depth); + } + const scope = getCurrentScope(); + const watchHandle = () => { + effect2.stop(); + if (scope && scope.active) { + remove(scope.effects, effect2); + } + }; + if (once && cb) { + const _cb = cb; + cb = (...args) => { + _cb(...args); + watchHandle(); + }; + } + let oldValue = isMultiSource ? new Array(source.length).fill(INITIAL_WATCHER_VALUE) : INITIAL_WATCHER_VALUE; + const job = (immediateFirstRun) => { + if (!(effect2.flags & 1) || !effect2.dirty && !immediateFirstRun) { + return; + } + if (cb) { + const newValue = effect2.run(); + if (deep || forceTrigger || (isMultiSource ? newValue.some((v, i) => hasChanged(v, oldValue[i])) : hasChanged(newValue, oldValue))) { + if (cleanup) { + cleanup(); + } + const currentWatcher = activeWatcher; + activeWatcher = effect2; + try { + const args = [ + newValue, + // pass undefined as the old value when it's changed for the first time + oldValue === INITIAL_WATCHER_VALUE ? void 0 : isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE ? [] : oldValue, + boundCleanup + ]; + oldValue = newValue; + call ? call(cb, 3, args) : ( + // @ts-expect-error + cb(...args) + ); + } finally { + activeWatcher = currentWatcher; + } + } + } else { + effect2.run(); + } + }; + if (augmentJob) { + augmentJob(job); + } + effect2 = new ReactiveEffect(getter); + effect2.scheduler = scheduler ? () => scheduler(job, false) : job; + boundCleanup = (fn) => onWatcherCleanup(fn, false, effect2); + cleanup = effect2.onStop = () => { + const cleanups = cleanupMap.get(effect2); + if (cleanups) { + if (call) { + call(cleanups, 4); + } else { + for (const cleanup2 of cleanups) cleanup2(); + } + cleanupMap.delete(effect2); + } + }; + if (true) { + effect2.onTrack = options.onTrack; + effect2.onTrigger = options.onTrigger; + } + if (cb) { + if (immediate) { + job(true); + } else { + oldValue = effect2.run(); + } + } else if (scheduler) { + scheduler(job.bind(null, true), true); + } else { + effect2.run(); + } + watchHandle.pause = effect2.pause.bind(effect2); + watchHandle.resume = effect2.resume.bind(effect2); + watchHandle.stop = watchHandle; + return watchHandle; +} +function traverse(value, depth = Infinity, seen) { + if (depth <= 0 || !isObject(value) || value["__v_skip"]) { + return value; + } + seen = seen || /* @__PURE__ */ new Map(); + if ((seen.get(value) || 0) >= depth) { + return value; + } + seen.set(value, depth); + depth--; + if (isRef2(value)) { + traverse(value.value, depth, seen); + } else if (isArray(value)) { + for (let i = 0; i < value.length; i++) { + traverse(value[i], depth, seen); + } + } else if (isSet(value) || isMap(value)) { + value.forEach((v) => { + traverse(v, depth, seen); + }); + } else if (isPlainObject(value)) { + for (const key in value) { + traverse(value[key], depth, seen); + } + for (const key of Object.getOwnPropertySymbols(value)) { + if (Object.prototype.propertyIsEnumerable.call(value, key)) { + traverse(value[key], depth, seen); + } + } + } + return value; +} + +// node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js +var stack = []; +function pushWarningContext(vnode) { + stack.push(vnode); +} +function popWarningContext() { + stack.pop(); +} +var isWarning = false; +function warn$1(msg, ...args) { + if (isWarning) return; + isWarning = true; + pauseTracking(); + const instance = stack.length ? stack[stack.length - 1].component : null; + const appWarnHandler = instance && instance.appContext.config.warnHandler; + const trace = getComponentTrace(); + if (appWarnHandler) { + callWithErrorHandling( + appWarnHandler, + instance, + 11, + [ + // eslint-disable-next-line no-restricted-syntax + msg + args.map((a) => { + var _a, _b; + return (_b = (_a = a.toString) == null ? void 0 : _a.call(a)) != null ? _b : JSON.stringify(a); + }).join(""), + instance && instance.proxy, + trace.map( + ({ vnode }) => `at <${formatComponentName(instance, vnode.type)}>` + ).join("\n"), + trace + ] + ); + } else { + const warnArgs = [`[Vue warn]: ${msg}`, ...args]; + if (trace.length && // avoid spamming console during tests + true) { + warnArgs.push(` +`, ...formatTrace(trace)); + } + console.warn(...warnArgs); + } + resetTracking(); + isWarning = false; +} +function getComponentTrace() { + let currentVNode = stack[stack.length - 1]; + if (!currentVNode) { + return []; + } + const normalizedStack = []; + while (currentVNode) { + const last = normalizedStack[0]; + if (last && last.vnode === currentVNode) { + last.recurseCount++; + } else { + normalizedStack.push({ + vnode: currentVNode, + recurseCount: 0 + }); + } + const parentInstance = currentVNode.component && currentVNode.component.parent; + currentVNode = parentInstance && parentInstance.vnode; + } + return normalizedStack; +} +function formatTrace(trace) { + const logs = []; + trace.forEach((entry, i) => { + logs.push(...i === 0 ? [] : [` +`], ...formatTraceEntry(entry)); + }); + return logs; +} +function formatTraceEntry({ vnode, recurseCount }) { + const postfix = recurseCount > 0 ? `... (${recurseCount} recursive calls)` : ``; + const isRoot = vnode.component ? vnode.component.parent == null : false; + const open = ` at <${formatComponentName( + vnode.component, + vnode.type, + isRoot + )}`; + const close = `>` + postfix; + return vnode.props ? [open, ...formatProps(vnode.props), close] : [open + close]; +} +function formatProps(props) { + const res = []; + const keys = Object.keys(props); + keys.slice(0, 3).forEach((key) => { + res.push(...formatProp(key, props[key])); + }); + if (keys.length > 3) { + res.push(` ...`); + } + return res; +} +function formatProp(key, value, raw) { + if (isString(value)) { + value = JSON.stringify(value); + return raw ? value : [`${key}=${value}`]; + } else if (typeof value === "number" || typeof value === "boolean" || value == null) { + return raw ? value : [`${key}=${value}`]; + } else if (isRef2(value)) { + value = formatProp(key, toRaw(value.value), true); + return raw ? value : [`${key}=Ref<`, value, `>`]; + } else if (isFunction(value)) { + return [`${key}=fn${value.name ? `<${value.name}>` : ``}`]; + } else { + value = toRaw(value); + return raw ? value : [`${key}=`, value]; + } +} +function assertNumber(val, type) { + if (false) return; + if (val === void 0) { + return; + } else if (typeof val !== "number") { + warn$1(`${type} is not a valid number - got ${JSON.stringify(val)}.`); + } else if (isNaN(val)) { + warn$1(`${type} is NaN - the duration expression might be incorrect.`); + } +} +var ErrorCodes = { + "SETUP_FUNCTION": 0, + "0": "SETUP_FUNCTION", + "RENDER_FUNCTION": 1, + "1": "RENDER_FUNCTION", + "NATIVE_EVENT_HANDLER": 5, + "5": "NATIVE_EVENT_HANDLER", + "COMPONENT_EVENT_HANDLER": 6, + "6": "COMPONENT_EVENT_HANDLER", + "VNODE_HOOK": 7, + "7": "VNODE_HOOK", + "DIRECTIVE_HOOK": 8, + "8": "DIRECTIVE_HOOK", + "TRANSITION_HOOK": 9, + "9": "TRANSITION_HOOK", + "APP_ERROR_HANDLER": 10, + "10": "APP_ERROR_HANDLER", + "APP_WARN_HANDLER": 11, + "11": "APP_WARN_HANDLER", + "FUNCTION_REF": 12, + "12": "FUNCTION_REF", + "ASYNC_COMPONENT_LOADER": 13, + "13": "ASYNC_COMPONENT_LOADER", + "SCHEDULER": 14, + "14": "SCHEDULER", + "COMPONENT_UPDATE": 15, + "15": "COMPONENT_UPDATE", + "APP_UNMOUNT_CLEANUP": 16, + "16": "APP_UNMOUNT_CLEANUP" +}; +var ErrorTypeStrings$1 = { + ["sp"]: "serverPrefetch hook", + ["bc"]: "beforeCreate hook", + ["c"]: "created hook", + ["bm"]: "beforeMount hook", + ["m"]: "mounted hook", + ["bu"]: "beforeUpdate hook", + ["u"]: "updated", + ["bum"]: "beforeUnmount hook", + ["um"]: "unmounted hook", + ["a"]: "activated hook", + ["da"]: "deactivated hook", + ["ec"]: "errorCaptured hook", + ["rtc"]: "renderTracked hook", + ["rtg"]: "renderTriggered hook", + [0]: "setup function", + [1]: "render function", + [2]: "watcher getter", + [3]: "watcher callback", + [4]: "watcher cleanup function", + [5]: "native event handler", + [6]: "component event handler", + [7]: "vnode hook", + [8]: "directive hook", + [9]: "transition hook", + [10]: "app errorHandler", + [11]: "app warnHandler", + [12]: "ref function", + [13]: "async component loader", + [14]: "scheduler flush", + [15]: "component update", + [16]: "app unmount cleanup function" +}; +function callWithErrorHandling(fn, instance, type, args) { + try { + return args ? fn(...args) : fn(); + } catch (err) { + handleError(err, instance, type); + } +} +function callWithAsyncErrorHandling(fn, instance, type, args) { + if (isFunction(fn)) { + const res = callWithErrorHandling(fn, instance, type, args); + if (res && isPromise(res)) { + res.catch((err) => { + handleError(err, instance, type); + }); + } + return res; + } + if (isArray(fn)) { + const values = []; + for (let i = 0; i < fn.length; i++) { + values.push(callWithAsyncErrorHandling(fn[i], instance, type, args)); + } + return values; + } else if (true) { + warn$1( + `Invalid value type passed to callWithAsyncErrorHandling(): ${typeof fn}` + ); + } +} +function handleError(err, instance, type, throwInDev = true) { + const contextVNode = instance ? instance.vnode : null; + const { errorHandler, throwUnhandledErrorInProduction } = instance && instance.appContext.config || EMPTY_OBJ; + if (instance) { + let cur = instance.parent; + const exposedInstance = instance.proxy; + const errorInfo = true ? ErrorTypeStrings$1[type] : `https://vuejs.org/error-reference/#runtime-${type}`; + while (cur) { + const errorCapturedHooks = cur.ec; + if (errorCapturedHooks) { + for (let i = 0; i < errorCapturedHooks.length; i++) { + if (errorCapturedHooks[i](err, exposedInstance, errorInfo) === false) { + return; + } + } + } + cur = cur.parent; + } + if (errorHandler) { + pauseTracking(); + callWithErrorHandling(errorHandler, null, 10, [ + err, + exposedInstance, + errorInfo + ]); + resetTracking(); + return; + } + } + logError(err, type, contextVNode, throwInDev, throwUnhandledErrorInProduction); +} +function logError(err, type, contextVNode, throwInDev = true, throwInProd = false) { + if (true) { + const info = ErrorTypeStrings$1[type]; + if (contextVNode) { + pushWarningContext(contextVNode); + } + warn$1(`Unhandled error${info ? ` during execution of ${info}` : ``}`); + if (contextVNode) { + popWarningContext(); + } + if (throwInDev) { + throw err; + } else { + console.error(err); + } + } else if (throwInProd) { + throw err; + } else { + console.error(err); + } +} +var queue = []; +var flushIndex = -1; +var pendingPostFlushCbs = []; +var activePostFlushCbs = null; +var postFlushIndex = 0; +var resolvedPromise = Promise.resolve(); +var currentFlushPromise = null; +var RECURSION_LIMIT = 100; +function nextTick(fn) { + const p2 = currentFlushPromise || resolvedPromise; + return fn ? p2.then(this ? fn.bind(this) : fn) : p2; +} +function findInsertionIndex(id) { + let start = flushIndex + 1; + let end = queue.length; + while (start < end) { + const middle = start + end >>> 1; + const middleJob = queue[middle]; + const middleJobId = getId(middleJob); + if (middleJobId < id || middleJobId === id && middleJob.flags & 2) { + start = middle + 1; + } else { + end = middle; + } + } + return start; +} +function queueJob(job) { + if (!(job.flags & 1)) { + const jobId = getId(job); + const lastJob = queue[queue.length - 1]; + if (!lastJob || // fast path when the job id is larger than the tail + !(job.flags & 2) && jobId >= getId(lastJob)) { + queue.push(job); + } else { + queue.splice(findInsertionIndex(jobId), 0, job); + } + job.flags |= 1; + queueFlush(); + } +} +function queueFlush() { + if (!currentFlushPromise) { + currentFlushPromise = resolvedPromise.then(flushJobs); + } +} +function queuePostFlushCb(cb) { + if (!isArray(cb)) { + if (activePostFlushCbs && cb.id === -1) { + activePostFlushCbs.splice(postFlushIndex + 1, 0, cb); + } else if (!(cb.flags & 1)) { + pendingPostFlushCbs.push(cb); + cb.flags |= 1; + } + } else { + pendingPostFlushCbs.push(...cb); + } + queueFlush(); +} +function flushPreFlushCbs(instance, seen, i = flushIndex + 1) { + if (true) { + seen = seen || /* @__PURE__ */ new Map(); + } + for (; i < queue.length; i++) { + const cb = queue[i]; + if (cb && cb.flags & 2) { + if (instance && cb.id !== instance.uid) { + continue; + } + if (checkRecursiveUpdates(seen, cb)) { + continue; + } + queue.splice(i, 1); + i--; + if (cb.flags & 4) { + cb.flags &= -2; + } + cb(); + if (!(cb.flags & 4)) { + cb.flags &= -2; + } + } + } +} +function flushPostFlushCbs(seen) { + if (pendingPostFlushCbs.length) { + const deduped = [...new Set(pendingPostFlushCbs)].sort( + (a, b) => getId(a) - getId(b) + ); + pendingPostFlushCbs.length = 0; + if (activePostFlushCbs) { + activePostFlushCbs.push(...deduped); + return; + } + activePostFlushCbs = deduped; + if (true) { + seen = seen || /* @__PURE__ */ new Map(); + } + for (postFlushIndex = 0; postFlushIndex < activePostFlushCbs.length; postFlushIndex++) { + const cb = activePostFlushCbs[postFlushIndex]; + if (checkRecursiveUpdates(seen, cb)) { + continue; + } + if (cb.flags & 4) { + cb.flags &= -2; + } + if (!(cb.flags & 8)) cb(); + cb.flags &= -2; + } + activePostFlushCbs = null; + postFlushIndex = 0; + } +} +var getId = (job) => job.id == null ? job.flags & 2 ? -1 : Infinity : job.id; +function flushJobs(seen) { + if (true) { + seen = seen || /* @__PURE__ */ new Map(); + } + const check = true ? (job) => checkRecursiveUpdates(seen, job) : NOOP; + try { + for (flushIndex = 0; flushIndex < queue.length; flushIndex++) { + const job = queue[flushIndex]; + if (job && !(job.flags & 8)) { + if (check(job)) { + continue; + } + if (job.flags & 4) { + job.flags &= ~1; + } + callWithErrorHandling( + job, + job.i, + job.i ? 15 : 14 + ); + if (!(job.flags & 4)) { + job.flags &= ~1; + } + } + } + } finally { + for (; flushIndex < queue.length; flushIndex++) { + const job = queue[flushIndex]; + if (job) { + job.flags &= -2; + } + } + flushIndex = -1; + queue.length = 0; + flushPostFlushCbs(seen); + currentFlushPromise = null; + if (queue.length || pendingPostFlushCbs.length) { + flushJobs(seen); + } + } +} +function checkRecursiveUpdates(seen, fn) { + const count = seen.get(fn) || 0; + if (count > RECURSION_LIMIT) { + const instance = fn.i; + const componentName = instance && getComponentName(instance.type); + handleError( + `Maximum recursive updates exceeded${componentName ? ` in component <${componentName}>` : ``}. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.`, + null, + 10 + ); + return true; + } + seen.set(fn, count + 1); + return false; +} +var isHmrUpdating = false; +var hmrDirtyComponents = /* @__PURE__ */ new Map(); +if (true) { + getGlobalThis().__VUE_HMR_RUNTIME__ = { + createRecord: tryWrap(createRecord), + rerender: tryWrap(rerender), + reload: tryWrap(reload) + }; +} +var map = /* @__PURE__ */ new Map(); +function registerHMR(instance) { + const id = instance.type.__hmrId; + let record = map.get(id); + if (!record) { + createRecord(id, instance.type); + record = map.get(id); + } + record.instances.add(instance); +} +function unregisterHMR(instance) { + map.get(instance.type.__hmrId).instances.delete(instance); +} +function createRecord(id, initialDef) { + if (map.has(id)) { + return false; + } + map.set(id, { + initialDef: normalizeClassComponent(initialDef), + instances: /* @__PURE__ */ new Set() + }); + return true; +} +function normalizeClassComponent(component) { + return isClassComponent(component) ? component.__vccOpts : component; +} +function rerender(id, newRender) { + const record = map.get(id); + if (!record) { + return; + } + record.initialDef.render = newRender; + [...record.instances].forEach((instance) => { + if (newRender) { + instance.render = newRender; + normalizeClassComponent(instance.type).render = newRender; + } + instance.renderCache = []; + isHmrUpdating = true; + if (!(instance.job.flags & 8)) { + instance.update(); + } + isHmrUpdating = false; + }); +} +function reload(id, newComp) { + const record = map.get(id); + if (!record) return; + newComp = normalizeClassComponent(newComp); + updateComponentDef(record.initialDef, newComp); + const instances = [...record.instances]; + for (let i = 0; i < instances.length; i++) { + const instance = instances[i]; + const oldComp = normalizeClassComponent(instance.type); + let dirtyInstances = hmrDirtyComponents.get(oldComp); + if (!dirtyInstances) { + if (oldComp !== record.initialDef) { + updateComponentDef(oldComp, newComp); + } + hmrDirtyComponents.set(oldComp, dirtyInstances = /* @__PURE__ */ new Set()); + } + dirtyInstances.add(instance); + instance.appContext.propsCache.delete(instance.type); + instance.appContext.emitsCache.delete(instance.type); + instance.appContext.optionsCache.delete(instance.type); + if (instance.ceReload) { + dirtyInstances.add(instance); + instance.ceReload(newComp.styles); + dirtyInstances.delete(instance); + } else if (instance.parent) { + queueJob(() => { + if (!(instance.job.flags & 8)) { + isHmrUpdating = true; + instance.parent.update(); + isHmrUpdating = false; + dirtyInstances.delete(instance); + } + }); + } else if (instance.appContext.reload) { + instance.appContext.reload(); + } else if (typeof window !== "undefined") { + window.location.reload(); + } else { + console.warn( + "[HMR] Root or manually mounted instance modified. Full reload required." + ); + } + if (instance.root.ce && instance !== instance.root) { + instance.root.ce._removeChildStyle(oldComp); + } + } + queuePostFlushCb(() => { + hmrDirtyComponents.clear(); + }); +} +function updateComponentDef(oldComp, newComp) { + extend(oldComp, newComp); + for (const key in oldComp) { + if (key !== "__file" && !(key in newComp)) { + delete oldComp[key]; + } + } +} +function tryWrap(fn) { + return (id, arg) => { + try { + return fn(id, arg); + } catch (e) { + console.error(e); + console.warn( + `[HMR] Something went wrong during Vue component hot-reload. Full reload required.` + ); + } + }; +} +var devtools$1; +var buffer = []; +var devtoolsNotInstalled = false; +function emit$1(event, ...args) { + if (devtools$1) { + devtools$1.emit(event, ...args); + } else if (!devtoolsNotInstalled) { + buffer.push({ event, args }); + } +} +function setDevtoolsHook$1(hook, target) { + var _a, _b; + devtools$1 = hook; + if (devtools$1) { + devtools$1.enabled = true; + buffer.forEach(({ event, args }) => devtools$1.emit(event, ...args)); + buffer = []; + } else if ( + // handle late devtools injection - only do this if we are in an actual + // browser environment to avoid the timer handle stalling test runner exit + // (#4815) + typeof window !== "undefined" && // some envs mock window but not fully + window.HTMLElement && // also exclude jsdom + // eslint-disable-next-line no-restricted-syntax + !((_b = (_a = window.navigator) == null ? void 0 : _a.userAgent) == null ? void 0 : _b.includes("jsdom")) + ) { + const replay = target.__VUE_DEVTOOLS_HOOK_REPLAY__ = target.__VUE_DEVTOOLS_HOOK_REPLAY__ || []; + replay.push((newHook) => { + setDevtoolsHook$1(newHook, target); + }); + setTimeout(() => { + if (!devtools$1) { + target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null; + devtoolsNotInstalled = true; + buffer = []; + } + }, 3e3); + } else { + devtoolsNotInstalled = true; + buffer = []; + } +} +function devtoolsInitApp(app, version2) { + emit$1("app:init", app, version2, { + Fragment, + Text, + Comment, + Static + }); +} +function devtoolsUnmountApp(app) { + emit$1("app:unmount", app); +} +var devtoolsComponentAdded = createDevtoolsComponentHook( + "component:added" + /* COMPONENT_ADDED */ +); +var devtoolsComponentUpdated = createDevtoolsComponentHook( + "component:updated" + /* COMPONENT_UPDATED */ +); +var _devtoolsComponentRemoved = createDevtoolsComponentHook( + "component:removed" + /* COMPONENT_REMOVED */ +); +var devtoolsComponentRemoved = (component) => { + if (devtools$1 && typeof devtools$1.cleanupBuffer === "function" && // remove the component if it wasn't buffered + !devtools$1.cleanupBuffer(component)) { + _devtoolsComponentRemoved(component); + } +}; +function createDevtoolsComponentHook(hook) { + return (component) => { + emit$1( + hook, + component.appContext.app, + component.uid, + component.parent ? component.parent.uid : void 0, + component + ); + }; +} +var devtoolsPerfStart = createDevtoolsPerformanceHook( + "perf:start" + /* PERFORMANCE_START */ +); +var devtoolsPerfEnd = createDevtoolsPerformanceHook( + "perf:end" + /* PERFORMANCE_END */ +); +function createDevtoolsPerformanceHook(hook) { + return (component, type, time) => { + emit$1(hook, component.appContext.app, component.uid, component, type, time); + }; +} +function devtoolsComponentEmit(component, event, params) { + emit$1( + "component:emit", + component.appContext.app, + component, + event, + params + ); +} +var currentRenderingInstance = null; +var currentScopeId = null; +function setCurrentRenderingInstance(instance) { + const prev = currentRenderingInstance; + currentRenderingInstance = instance; + currentScopeId = instance && instance.type.__scopeId || null; + return prev; +} +function pushScopeId(id) { + currentScopeId = id; +} +function popScopeId() { + currentScopeId = null; +} +var withScopeId = (_id) => withCtx; +function withCtx(fn, ctx = currentRenderingInstance, isNonScopedSlot) { + if (!ctx) return fn; + if (fn._n) { + return fn; + } + const renderFnWithContext = (...args) => { + if (renderFnWithContext._d) { + setBlockTracking(-1); + } + const prevInstance = setCurrentRenderingInstance(ctx); + let res; + try { + res = fn(...args); + } finally { + setCurrentRenderingInstance(prevInstance); + if (renderFnWithContext._d) { + setBlockTracking(1); + } + } + if (true) { + devtoolsComponentUpdated(ctx); + } + return res; + }; + renderFnWithContext._n = true; + renderFnWithContext._c = true; + renderFnWithContext._d = true; + return renderFnWithContext; +} +function validateDirectiveName(name) { + if (isBuiltInDirective(name)) { + warn$1("Do not use built-in directive ids as custom directive id: " + name); + } +} +function withDirectives(vnode, directives) { + if (currentRenderingInstance === null) { + warn$1(`withDirectives can only be used inside render functions.`); + return vnode; + } + const instance = getComponentPublicInstance(currentRenderingInstance); + const bindings = vnode.dirs || (vnode.dirs = []); + for (let i = 0; i < directives.length; i++) { + let [dir, value, arg, modifiers = EMPTY_OBJ] = directives[i]; + if (dir) { + if (isFunction(dir)) { + dir = { + mounted: dir, + updated: dir + }; + } + if (dir.deep) { + traverse(value); + } + bindings.push({ + dir, + instance, + value, + oldValue: void 0, + arg, + modifiers + }); + } + } + return vnode; +} +function invokeDirectiveHook(vnode, prevVNode, instance, name) { + const bindings = vnode.dirs; + const oldBindings = prevVNode && prevVNode.dirs; + for (let i = 0; i < bindings.length; i++) { + const binding = bindings[i]; + if (oldBindings) { + binding.oldValue = oldBindings[i].value; + } + let hook = binding.dir[name]; + if (hook) { + pauseTracking(); + callWithAsyncErrorHandling(hook, instance, 8, [ + vnode.el, + binding, + vnode, + prevVNode + ]); + resetTracking(); + } + } +} +function provide(key, value) { + if (true) { + if (!currentInstance || currentInstance.isMounted) { + warn$1(`provide() can only be used inside setup().`); + } + } + if (currentInstance) { + let provides = currentInstance.provides; + const parentProvides = currentInstance.parent && currentInstance.parent.provides; + if (parentProvides === provides) { + provides = currentInstance.provides = Object.create(parentProvides); + } + provides[key] = value; + } +} +function inject(key, defaultValue, treatDefaultAsFactory = false) { + const instance = getCurrentInstance(); + if (instance || currentApp) { + let provides = currentApp ? currentApp._context.provides : instance ? instance.parent == null || instance.ce ? instance.vnode.appContext && instance.vnode.appContext.provides : instance.parent.provides : void 0; + if (provides && key in provides) { + return provides[key]; + } else if (arguments.length > 1) { + return treatDefaultAsFactory && isFunction(defaultValue) ? defaultValue.call(instance && instance.proxy) : defaultValue; + } else if (true) { + warn$1(`injection "${String(key)}" not found.`); + } + } else if (true) { + warn$1(`inject() can only be used inside setup() or functional components.`); + } +} +function hasInjectionContext() { + return !!(getCurrentInstance() || currentApp); +} +var ssrContextKey = Symbol.for("v-scx"); +var useSSRContext = () => { + { + const ctx = inject(ssrContextKey); + if (!ctx) { + warn$1( + `Server rendering context not provided. Make sure to only call useSSRContext() conditionally in the server build.` + ); + } + return ctx; + } +}; +function watchEffect(effect2, options) { + return doWatch(effect2, null, options); +} +function watchPostEffect(effect2, options) { + return doWatch( + effect2, + null, + true ? extend({}, options, { flush: "post" }) : { flush: "post" } + ); +} +function watchSyncEffect(effect2, options) { + return doWatch( + effect2, + null, + true ? extend({}, options, { flush: "sync" }) : { flush: "sync" } + ); +} +function watch2(source, cb, options) { + if (!isFunction(cb)) { + warn$1( + `\`watch(fn, options?)\` signature has been moved to a separate API. Use \`watchEffect(fn, options?)\` instead. \`watch\` now only supports \`watch(source, cb, options?) signature.` + ); + } + return doWatch(source, cb, options); +} +function doWatch(source, cb, options = EMPTY_OBJ) { + const { immediate, deep, flush, once } = options; + if (!cb) { + if (immediate !== void 0) { + warn$1( + `watch() "immediate" option is only respected when using the watch(source, callback, options?) signature.` + ); + } + if (deep !== void 0) { + warn$1( + `watch() "deep" option is only respected when using the watch(source, callback, options?) signature.` + ); + } + if (once !== void 0) { + warn$1( + `watch() "once" option is only respected when using the watch(source, callback, options?) signature.` + ); + } + } + const baseWatchOptions = extend({}, options); + if (true) baseWatchOptions.onWarn = warn$1; + const runsImmediately = cb && immediate || !cb && flush !== "post"; + let ssrCleanup; + if (isInSSRComponentSetup) { + if (flush === "sync") { + const ctx = useSSRContext(); + ssrCleanup = ctx.__watcherHandles || (ctx.__watcherHandles = []); + } else if (!runsImmediately) { + const watchStopHandle = () => { + }; + watchStopHandle.stop = NOOP; + watchStopHandle.resume = NOOP; + watchStopHandle.pause = NOOP; + return watchStopHandle; + } + } + const instance = currentInstance; + baseWatchOptions.call = (fn, type, args) => callWithAsyncErrorHandling(fn, instance, type, args); + let isPre = false; + if (flush === "post") { + baseWatchOptions.scheduler = (job) => { + queuePostRenderEffect(job, instance && instance.suspense); + }; + } else if (flush !== "sync") { + isPre = true; + baseWatchOptions.scheduler = (job, isFirstRun) => { + if (isFirstRun) { + job(); + } else { + queueJob(job); + } + }; + } + baseWatchOptions.augmentJob = (job) => { + if (cb) { + job.flags |= 4; + } + if (isPre) { + job.flags |= 2; + if (instance) { + job.id = instance.uid; + job.i = instance; + } + } + }; + const watchHandle = watch(source, cb, baseWatchOptions); + if (isInSSRComponentSetup) { + if (ssrCleanup) { + ssrCleanup.push(watchHandle); + } else if (runsImmediately) { + watchHandle(); + } + } + return watchHandle; +} +function instanceWatch(source, value, options) { + const publicThis = this.proxy; + const getter = isString(source) ? source.includes(".") ? createPathGetter(publicThis, source) : () => publicThis[source] : source.bind(publicThis, publicThis); + let cb; + if (isFunction(value)) { + cb = value; + } else { + cb = value.handler; + options = value; + } + const reset = setCurrentInstance(this); + const res = doWatch(getter, cb.bind(publicThis), options); + reset(); + return res; +} +function createPathGetter(ctx, path) { + const segments = path.split("."); + return () => { + let cur = ctx; + for (let i = 0; i < segments.length && cur; i++) { + cur = cur[segments[i]]; + } + return cur; + }; +} +var TeleportEndKey = Symbol("_vte"); +var isTeleport = (type) => type.__isTeleport; +var isTeleportDisabled = (props) => props && (props.disabled || props.disabled === ""); +var isTeleportDeferred = (props) => props && (props.defer || props.defer === ""); +var isTargetSVG = (target) => typeof SVGElement !== "undefined" && target instanceof SVGElement; +var isTargetMathML = (target) => typeof MathMLElement === "function" && target instanceof MathMLElement; +var resolveTarget = (props, select) => { + const targetSelector = props && props.to; + if (isString(targetSelector)) { + if (!select) { + warn$1( + `Current renderer does not support string target for Teleports. (missing querySelector renderer option)` + ); + return null; + } else { + const target = select(targetSelector); + if (!target && !isTeleportDisabled(props)) { + warn$1( + `Failed to locate Teleport target with selector "${targetSelector}". Note the target element must exist before the component is mounted - i.e. the target cannot be rendered by the component itself, and ideally should be outside of the entire Vue component tree.` + ); + } + return target; + } + } else { + if (!targetSelector && !isTeleportDisabled(props)) { + warn$1(`Invalid Teleport target: ${targetSelector}`); + } + return targetSelector; + } +}; +var TeleportImpl = { + name: "Teleport", + __isTeleport: true, + process(n1, n2, container, anchor, parentComponent, parentSuspense, namespace, slotScopeIds, optimized, internals) { + const { + mc: mountChildren, + pc: patchChildren, + pbc: patchBlockChildren, + o: { insert, querySelector, createText, createComment } + } = internals; + const disabled = isTeleportDisabled(n2.props); + let { shapeFlag, children, dynamicChildren } = n2; + if (isHmrUpdating) { + optimized = false; + dynamicChildren = null; + } + if (n1 == null) { + const placeholder = n2.el = true ? createComment("teleport start") : createText(""); + const mainAnchor = n2.anchor = true ? createComment("teleport end") : createText(""); + insert(placeholder, container, anchor); + insert(mainAnchor, container, anchor); + const mount = (container2, anchor2) => { + if (shapeFlag & 16) { + mountChildren( + children, + container2, + anchor2, + parentComponent, + parentSuspense, + namespace, + slotScopeIds, + optimized + ); + } + }; + const mountToTarget = () => { + const target = n2.target = resolveTarget(n2.props, querySelector); + const targetAnchor = prepareAnchor(target, n2, createText, insert); + if (target) { + if (namespace !== "svg" && isTargetSVG(target)) { + namespace = "svg"; + } else if (namespace !== "mathml" && isTargetMathML(target)) { + namespace = "mathml"; + } + if (parentComponent && parentComponent.isCE) { + (parentComponent.ce._teleportTargets || (parentComponent.ce._teleportTargets = /* @__PURE__ */ new Set())).add(target); + } + if (!disabled) { + mount(target, targetAnchor); + updateCssVars(n2, false); + } + } else if (!disabled) { + warn$1( + "Invalid Teleport target on mount:", + target, + `(${typeof target})` + ); + } + }; + if (disabled) { + mount(container, mainAnchor); + updateCssVars(n2, true); + } + if (isTeleportDeferred(n2.props)) { + n2.el.__isMounted = false; + queuePostRenderEffect(() => { + mountToTarget(); + delete n2.el.__isMounted; + }, parentSuspense); + } else { + mountToTarget(); + } + } else { + if (isTeleportDeferred(n2.props) && n1.el.__isMounted === false) { + queuePostRenderEffect(() => { + TeleportImpl.process( + n1, + n2, + container, + anchor, + parentComponent, + parentSuspense, + namespace, + slotScopeIds, + optimized, + internals + ); + }, parentSuspense); + return; + } + n2.el = n1.el; + n2.targetStart = n1.targetStart; + const mainAnchor = n2.anchor = n1.anchor; + const target = n2.target = n1.target; + const targetAnchor = n2.targetAnchor = n1.targetAnchor; + const wasDisabled = isTeleportDisabled(n1.props); + const currentContainer = wasDisabled ? container : target; + const currentAnchor = wasDisabled ? mainAnchor : targetAnchor; + if (namespace === "svg" || isTargetSVG(target)) { + namespace = "svg"; + } else if (namespace === "mathml" || isTargetMathML(target)) { + namespace = "mathml"; + } + if (dynamicChildren) { + patchBlockChildren( + n1.dynamicChildren, + dynamicChildren, + currentContainer, + parentComponent, + parentSuspense, + namespace, + slotScopeIds + ); + traverseStaticChildren(n1, n2, false); + } else if (!optimized) { + patchChildren( + n1, + n2, + currentContainer, + currentAnchor, + parentComponent, + parentSuspense, + namespace, + slotScopeIds, + false + ); + } + if (disabled) { + if (!wasDisabled) { + moveTeleport( + n2, + container, + mainAnchor, + internals, + 1 + ); + } else { + if (n2.props && n1.props && n2.props.to !== n1.props.to) { + n2.props.to = n1.props.to; + } + } + } else { + if ((n2.props && n2.props.to) !== (n1.props && n1.props.to)) { + const nextTarget = n2.target = resolveTarget( + n2.props, + querySelector + ); + if (nextTarget) { + moveTeleport( + n2, + nextTarget, + null, + internals, + 0 + ); + } else if (true) { + warn$1( + "Invalid Teleport target on update:", + target, + `(${typeof target})` + ); + } + } else if (wasDisabled) { + moveTeleport( + n2, + target, + targetAnchor, + internals, + 1 + ); + } + } + updateCssVars(n2, disabled); + } + }, + remove(vnode, parentComponent, parentSuspense, { um: unmount, o: { remove: hostRemove } }, doRemove) { + const { + shapeFlag, + children, + anchor, + targetStart, + targetAnchor, + target, + props + } = vnode; + if (target) { + hostRemove(targetStart); + hostRemove(targetAnchor); + } + doRemove && hostRemove(anchor); + if (shapeFlag & 16) { + const shouldRemove = doRemove || !isTeleportDisabled(props); + for (let i = 0; i < children.length; i++) { + const child = children[i]; + unmount( + child, + parentComponent, + parentSuspense, + shouldRemove, + !!child.dynamicChildren + ); + } + } + }, + move: moveTeleport, + hydrate: hydrateTeleport +}; +function moveTeleport(vnode, container, parentAnchor, { o: { insert }, m: move }, moveType = 2) { + if (moveType === 0) { + insert(vnode.targetAnchor, container, parentAnchor); + } + const { el, anchor, shapeFlag, children, props } = vnode; + const isReorder = moveType === 2; + if (isReorder) { + insert(el, container, parentAnchor); + } + if (!isReorder || isTeleportDisabled(props)) { + if (shapeFlag & 16) { + for (let i = 0; i < children.length; i++) { + move( + children[i], + container, + parentAnchor, + 2 + ); + } + } + } + if (isReorder) { + insert(anchor, container, parentAnchor); + } +} +function hydrateTeleport(node, vnode, parentComponent, parentSuspense, slotScopeIds, optimized, { + o: { nextSibling, parentNode, querySelector, insert, createText } +}, hydrateChildren) { + function hydrateDisabledTeleport(node2, vnode2, targetStart, targetAnchor) { + vnode2.anchor = hydrateChildren( + nextSibling(node2), + vnode2, + parentNode(node2), + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + vnode2.targetStart = targetStart; + vnode2.targetAnchor = targetAnchor; + } + const target = vnode.target = resolveTarget( + vnode.props, + querySelector + ); + const disabled = isTeleportDisabled(vnode.props); + if (target) { + const targetNode = target._lpa || target.firstChild; + if (vnode.shapeFlag & 16) { + if (disabled) { + hydrateDisabledTeleport( + node, + vnode, + targetNode, + targetNode && nextSibling(targetNode) + ); + } else { + vnode.anchor = nextSibling(node); + let targetAnchor = targetNode; + while (targetAnchor) { + if (targetAnchor && targetAnchor.nodeType === 8) { + if (targetAnchor.data === "teleport start anchor") { + vnode.targetStart = targetAnchor; + } else if (targetAnchor.data === "teleport anchor") { + vnode.targetAnchor = targetAnchor; + target._lpa = vnode.targetAnchor && nextSibling(vnode.targetAnchor); + break; + } + } + targetAnchor = nextSibling(targetAnchor); + } + if (!vnode.targetAnchor) { + prepareAnchor(target, vnode, createText, insert); + } + hydrateChildren( + targetNode && nextSibling(targetNode), + vnode, + target, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + } + } + updateCssVars(vnode, disabled); + } else if (disabled) { + if (vnode.shapeFlag & 16) { + hydrateDisabledTeleport(node, vnode, node, nextSibling(node)); + } + } + return vnode.anchor && nextSibling(vnode.anchor); +} +var Teleport = TeleportImpl; +function updateCssVars(vnode, isDisabled) { + const ctx = vnode.ctx; + if (ctx && ctx.ut) { + let node, anchor; + if (isDisabled) { + node = vnode.el; + anchor = vnode.anchor; + } else { + node = vnode.targetStart; + anchor = vnode.targetAnchor; + } + while (node && node !== anchor) { + if (node.nodeType === 1) node.setAttribute("data-v-owner", ctx.uid); + node = node.nextSibling; + } + ctx.ut(); + } +} +function prepareAnchor(target, vnode, createText, insert) { + const targetStart = vnode.targetStart = createText(""); + const targetAnchor = vnode.targetAnchor = createText(""); + targetStart[TeleportEndKey] = targetAnchor; + if (target) { + insert(targetStart, target); + insert(targetAnchor, target); + } + return targetAnchor; +} +var leaveCbKey = Symbol("_leaveCb"); +var enterCbKey = Symbol("_enterCb"); +function useTransitionState() { + const state = { + isMounted: false, + isLeaving: false, + isUnmounting: false, + leavingVNodes: /* @__PURE__ */ new Map() + }; + onMounted(() => { + state.isMounted = true; + }); + onBeforeUnmount(() => { + state.isUnmounting = true; + }); + return state; +} +var TransitionHookValidator = [Function, Array]; +var BaseTransitionPropsValidators = { + mode: String, + appear: Boolean, + persisted: Boolean, + // enter + onBeforeEnter: TransitionHookValidator, + onEnter: TransitionHookValidator, + onAfterEnter: TransitionHookValidator, + onEnterCancelled: TransitionHookValidator, + // leave + onBeforeLeave: TransitionHookValidator, + onLeave: TransitionHookValidator, + onAfterLeave: TransitionHookValidator, + onLeaveCancelled: TransitionHookValidator, + // appear + onBeforeAppear: TransitionHookValidator, + onAppear: TransitionHookValidator, + onAfterAppear: TransitionHookValidator, + onAppearCancelled: TransitionHookValidator +}; +var recursiveGetSubtree = (instance) => { + const subTree = instance.subTree; + return subTree.component ? recursiveGetSubtree(subTree.component) : subTree; +}; +var BaseTransitionImpl = { + name: `BaseTransition`, + props: BaseTransitionPropsValidators, + setup(props, { slots }) { + const instance = getCurrentInstance(); + const state = useTransitionState(); + return () => { + const children = slots.default && getTransitionRawChildren(slots.default(), true); + if (!children || !children.length) { + return; + } + const child = findNonCommentChild(children); + const rawProps = toRaw(props); + const { mode } = rawProps; + if (mode && mode !== "in-out" && mode !== "out-in" && mode !== "default") { + warn$1(`invalid mode: ${mode}`); + } + if (state.isLeaving) { + return emptyPlaceholder(child); + } + const innerChild = getInnerChild$1(child); + if (!innerChild) { + return emptyPlaceholder(child); + } + let enterHooks = resolveTransitionHooks( + innerChild, + rawProps, + state, + instance, + // #11061, ensure enterHooks is fresh after clone + (hooks) => enterHooks = hooks + ); + if (innerChild.type !== Comment) { + setTransitionHooks(innerChild, enterHooks); + } + let oldInnerChild = instance.subTree && getInnerChild$1(instance.subTree); + if (oldInnerChild && oldInnerChild.type !== Comment && !isSameVNodeType(oldInnerChild, innerChild) && recursiveGetSubtree(instance).type !== Comment) { + let leavingHooks = resolveTransitionHooks( + oldInnerChild, + rawProps, + state, + instance + ); + setTransitionHooks(oldInnerChild, leavingHooks); + if (mode === "out-in" && innerChild.type !== Comment) { + state.isLeaving = true; + leavingHooks.afterLeave = () => { + state.isLeaving = false; + if (!(instance.job.flags & 8)) { + instance.update(); + } + delete leavingHooks.afterLeave; + oldInnerChild = void 0; + }; + return emptyPlaceholder(child); + } else if (mode === "in-out" && innerChild.type !== Comment) { + leavingHooks.delayLeave = (el, earlyRemove, delayedLeave) => { + const leavingVNodesCache = getLeavingNodesForType( + state, + oldInnerChild + ); + leavingVNodesCache[String(oldInnerChild.key)] = oldInnerChild; + el[leaveCbKey] = () => { + earlyRemove(); + el[leaveCbKey] = void 0; + delete enterHooks.delayedLeave; + oldInnerChild = void 0; + }; + enterHooks.delayedLeave = () => { + delayedLeave(); + delete enterHooks.delayedLeave; + oldInnerChild = void 0; + }; + }; + } else { + oldInnerChild = void 0; + } + } else if (oldInnerChild) { + oldInnerChild = void 0; + } + return child; + }; + } +}; +function findNonCommentChild(children) { + let child = children[0]; + if (children.length > 1) { + let hasFound = false; + for (const c of children) { + if (c.type !== Comment) { + if (hasFound) { + warn$1( + " can only be used on a single element or component. Use for lists." + ); + break; + } + child = c; + hasFound = true; + if (false) break; + } + } + } + return child; +} +var BaseTransition = BaseTransitionImpl; +function getLeavingNodesForType(state, vnode) { + const { leavingVNodes } = state; + let leavingVNodesCache = leavingVNodes.get(vnode.type); + if (!leavingVNodesCache) { + leavingVNodesCache = /* @__PURE__ */ Object.create(null); + leavingVNodes.set(vnode.type, leavingVNodesCache); + } + return leavingVNodesCache; +} +function resolveTransitionHooks(vnode, props, state, instance, postClone) { + const { + appear, + mode, + persisted = false, + onBeforeEnter, + onEnter, + onAfterEnter, + onEnterCancelled, + onBeforeLeave, + onLeave, + onAfterLeave, + onLeaveCancelled, + onBeforeAppear, + onAppear, + onAfterAppear, + onAppearCancelled + } = props; + const key = String(vnode.key); + const leavingVNodesCache = getLeavingNodesForType(state, vnode); + const callHook3 = (hook, args) => { + hook && callWithAsyncErrorHandling( + hook, + instance, + 9, + args + ); + }; + const callAsyncHook = (hook, args) => { + const done = args[1]; + callHook3(hook, args); + if (isArray(hook)) { + if (hook.every((hook2) => hook2.length <= 1)) done(); + } else if (hook.length <= 1) { + done(); + } + }; + const hooks = { + mode, + persisted, + beforeEnter(el) { + let hook = onBeforeEnter; + if (!state.isMounted) { + if (appear) { + hook = onBeforeAppear || onBeforeEnter; + } else { + return; + } + } + if (el[leaveCbKey]) { + el[leaveCbKey]( + true + /* cancelled */ + ); + } + const leavingVNode = leavingVNodesCache[key]; + if (leavingVNode && isSameVNodeType(vnode, leavingVNode) && leavingVNode.el[leaveCbKey]) { + leavingVNode.el[leaveCbKey](); + } + callHook3(hook, [el]); + }, + enter(el) { + let hook = onEnter; + let afterHook = onAfterEnter; + let cancelHook = onEnterCancelled; + if (!state.isMounted) { + if (appear) { + hook = onAppear || onEnter; + afterHook = onAfterAppear || onAfterEnter; + cancelHook = onAppearCancelled || onEnterCancelled; + } else { + return; + } + } + let called = false; + const done = el[enterCbKey] = (cancelled) => { + if (called) return; + called = true; + if (cancelled) { + callHook3(cancelHook, [el]); + } else { + callHook3(afterHook, [el]); + } + if (hooks.delayedLeave) { + hooks.delayedLeave(); + } + el[enterCbKey] = void 0; + }; + if (hook) { + callAsyncHook(hook, [el, done]); + } else { + done(); + } + }, + leave(el, remove2) { + const key2 = String(vnode.key); + if (el[enterCbKey]) { + el[enterCbKey]( + true + /* cancelled */ + ); + } + if (state.isUnmounting) { + return remove2(); + } + callHook3(onBeforeLeave, [el]); + let called = false; + const done = el[leaveCbKey] = (cancelled) => { + if (called) return; + called = true; + remove2(); + if (cancelled) { + callHook3(onLeaveCancelled, [el]); + } else { + callHook3(onAfterLeave, [el]); + } + el[leaveCbKey] = void 0; + if (leavingVNodesCache[key2] === vnode) { + delete leavingVNodesCache[key2]; + } + }; + leavingVNodesCache[key2] = vnode; + if (onLeave) { + callAsyncHook(onLeave, [el, done]); + } else { + done(); + } + }, + clone(vnode2) { + const hooks2 = resolveTransitionHooks( + vnode2, + props, + state, + instance, + postClone + ); + if (postClone) postClone(hooks2); + return hooks2; + } + }; + return hooks; +} +function emptyPlaceholder(vnode) { + if (isKeepAlive(vnode)) { + vnode = cloneVNode(vnode); + vnode.children = null; + return vnode; + } +} +function getInnerChild$1(vnode) { + if (!isKeepAlive(vnode)) { + if (isTeleport(vnode.type) && vnode.children) { + return findNonCommentChild(vnode.children); + } + return vnode; + } + if (vnode.component) { + return vnode.component.subTree; + } + const { shapeFlag, children } = vnode; + if (children) { + if (shapeFlag & 16) { + return children[0]; + } + if (shapeFlag & 32 && isFunction(children.default)) { + return children.default(); + } + } +} +function setTransitionHooks(vnode, hooks) { + if (vnode.shapeFlag & 6 && vnode.component) { + vnode.transition = hooks; + setTransitionHooks(vnode.component.subTree, hooks); + } else if (vnode.shapeFlag & 128) { + vnode.ssContent.transition = hooks.clone(vnode.ssContent); + vnode.ssFallback.transition = hooks.clone(vnode.ssFallback); + } else { + vnode.transition = hooks; + } +} +function getTransitionRawChildren(children, keepComment = false, parentKey) { + let ret = []; + let keyedFragmentCount = 0; + for (let i = 0; i < children.length; i++) { + let child = children[i]; + const key = parentKey == null ? child.key : String(parentKey) + String(child.key != null ? child.key : i); + if (child.type === Fragment) { + if (child.patchFlag & 128) keyedFragmentCount++; + ret = ret.concat( + getTransitionRawChildren(child.children, keepComment, key) + ); + } else if (keepComment || child.type !== Comment) { + ret.push(key != null ? cloneVNode(child, { key }) : child); + } + } + if (keyedFragmentCount > 1) { + for (let i = 0; i < ret.length; i++) { + ret[i].patchFlag = -2; + } + } + return ret; +} +function defineComponent(options, extraOptions) { + return isFunction(options) ? ( + // #8236: extend call and options.name access are considered side-effects + // by Rollup, so we have to wrap it in a pure-annotated IIFE. + (() => extend({ name: options.name }, extraOptions, { setup: options }))() + ) : options; +} +function useId() { + const i = getCurrentInstance(); + if (i) { + return (i.appContext.config.idPrefix || "v") + "-" + i.ids[0] + i.ids[1]++; + } else if (true) { + warn$1( + `useId() is called when there is no active component instance to be associated with.` + ); + } + return ""; +} +function markAsyncBoundary(instance) { + instance.ids = [instance.ids[0] + instance.ids[2]++ + "-", 0, 0]; +} +var knownTemplateRefs = /* @__PURE__ */ new WeakSet(); +function useTemplateRef(key) { + const i = getCurrentInstance(); + const r = shallowRef(null); + if (i) { + const refs = i.refs === EMPTY_OBJ ? i.refs = {} : i.refs; + let desc; + if ((desc = Object.getOwnPropertyDescriptor(refs, key)) && !desc.configurable) { + warn$1(`useTemplateRef('${key}') already exists.`); + } else { + Object.defineProperty(refs, key, { + enumerable: true, + get: () => r.value, + set: (val) => r.value = val + }); + } + } else if (true) { + warn$1( + `useTemplateRef() is called when there is no active component instance to be associated with.` + ); + } + const ret = true ? readonly(r) : r; + if (true) { + knownTemplateRefs.add(ret); + } + return ret; +} +var pendingSetRefMap = /* @__PURE__ */ new WeakMap(); +function setRef(rawRef, oldRawRef, parentSuspense, vnode, isUnmount = false) { + if (isArray(rawRef)) { + rawRef.forEach( + (r, i) => setRef( + r, + oldRawRef && (isArray(oldRawRef) ? oldRawRef[i] : oldRawRef), + parentSuspense, + vnode, + isUnmount + ) + ); + return; + } + if (isAsyncWrapper(vnode) && !isUnmount) { + if (vnode.shapeFlag & 512 && vnode.type.__asyncResolved && vnode.component.subTree.component) { + setRef(rawRef, oldRawRef, parentSuspense, vnode.component.subTree); + } + return; + } + const refValue = vnode.shapeFlag & 4 ? getComponentPublicInstance(vnode.component) : vnode.el; + const value = isUnmount ? null : refValue; + const { i: owner, r: ref2 } = rawRef; + if (!owner) { + warn$1( + `Missing ref owner context. ref cannot be used on hoisted vnodes. A vnode with ref must be created inside the render function.` + ); + return; + } + const oldRef = oldRawRef && oldRawRef.r; + const refs = owner.refs === EMPTY_OBJ ? owner.refs = {} : owner.refs; + const setupState = owner.setupState; + const rawSetupState = toRaw(setupState); + const canSetSetupRef = setupState === EMPTY_OBJ ? NO : (key) => { + if (true) { + if (hasOwn(rawSetupState, key) && !isRef2(rawSetupState[key])) { + warn$1( + `Template ref "${key}" used on a non-ref value. It will not work in the production build.` + ); + } + if (knownTemplateRefs.has(rawSetupState[key])) { + return false; + } + } + return hasOwn(rawSetupState, key); + }; + const canSetRef = (ref22) => { + return !knownTemplateRefs.has(ref22); + }; + if (oldRef != null && oldRef !== ref2) { + invalidatePendingSetRef(oldRawRef); + if (isString(oldRef)) { + refs[oldRef] = null; + if (canSetSetupRef(oldRef)) { + setupState[oldRef] = null; + } + } else if (isRef2(oldRef)) { + if (canSetRef(oldRef)) { + oldRef.value = null; + } + const oldRawRefAtom = oldRawRef; + if (oldRawRefAtom.k) refs[oldRawRefAtom.k] = null; + } + } + if (isFunction(ref2)) { + callWithErrorHandling(ref2, owner, 12, [value, refs]); + } else { + const _isString = isString(ref2); + const _isRef = isRef2(ref2); + if (_isString || _isRef) { + const doSet = () => { + if (rawRef.f) { + const existing = _isString ? canSetSetupRef(ref2) ? setupState[ref2] : refs[ref2] : canSetRef(ref2) || !rawRef.k ? ref2.value : refs[rawRef.k]; + if (isUnmount) { + isArray(existing) && remove(existing, refValue); + } else { + if (!isArray(existing)) { + if (_isString) { + refs[ref2] = [refValue]; + if (canSetSetupRef(ref2)) { + setupState[ref2] = refs[ref2]; + } + } else { + const newVal = [refValue]; + if (canSetRef(ref2)) { + ref2.value = newVal; + } + if (rawRef.k) refs[rawRef.k] = newVal; + } + } else if (!existing.includes(refValue)) { + existing.push(refValue); + } + } + } else if (_isString) { + refs[ref2] = value; + if (canSetSetupRef(ref2)) { + setupState[ref2] = value; + } + } else if (_isRef) { + if (canSetRef(ref2)) { + ref2.value = value; + } + if (rawRef.k) refs[rawRef.k] = value; + } else if (true) { + warn$1("Invalid template ref type:", ref2, `(${typeof ref2})`); + } + }; + if (value) { + const job = () => { + doSet(); + pendingSetRefMap.delete(rawRef); + }; + job.id = -1; + pendingSetRefMap.set(rawRef, job); + queuePostRenderEffect(job, parentSuspense); + } else { + invalidatePendingSetRef(rawRef); + doSet(); + } + } else if (true) { + warn$1("Invalid template ref type:", ref2, `(${typeof ref2})`); + } + } +} +function invalidatePendingSetRef(rawRef) { + const pendingSetRef = pendingSetRefMap.get(rawRef); + if (pendingSetRef) { + pendingSetRef.flags |= 8; + pendingSetRefMap.delete(rawRef); + } +} +var hasLoggedMismatchError = false; +var logMismatchError = () => { + if (hasLoggedMismatchError) { + return; + } + console.error("Hydration completed but contains mismatches."); + hasLoggedMismatchError = true; +}; +var isSVGContainer = (container) => container.namespaceURI.includes("svg") && container.tagName !== "foreignObject"; +var isMathMLContainer = (container) => container.namespaceURI.includes("MathML"); +var getContainerType = (container) => { + if (container.nodeType !== 1) return void 0; + if (isSVGContainer(container)) return "svg"; + if (isMathMLContainer(container)) return "mathml"; + return void 0; +}; +var isComment = (node) => node.nodeType === 8; +function createHydrationFunctions(rendererInternals) { + const { + mt: mountComponent, + p: patch, + o: { + patchProp: patchProp2, + createText, + nextSibling, + parentNode, + remove: remove2, + insert, + createComment + } + } = rendererInternals; + const hydrate2 = (vnode, container) => { + if (!container.hasChildNodes()) { + warn$1( + `Attempting to hydrate existing markup but container is empty. Performing full mount instead.` + ); + patch(null, vnode, container); + flushPostFlushCbs(); + container._vnode = vnode; + return; + } + hydrateNode(container.firstChild, vnode, null, null, null); + flushPostFlushCbs(); + container._vnode = vnode; + }; + const hydrateNode = (node, vnode, parentComponent, parentSuspense, slotScopeIds, optimized = false) => { + optimized = optimized || !!vnode.dynamicChildren; + const isFragmentStart = isComment(node) && node.data === "["; + const onMismatch = () => handleMismatch( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + isFragmentStart + ); + const { type, ref: ref2, shapeFlag, patchFlag } = vnode; + let domType = node.nodeType; + vnode.el = node; + if (true) { + def(node, "__vnode", vnode, true); + def(node, "__vueParentComponent", parentComponent, true); + } + if (patchFlag === -2) { + optimized = false; + vnode.dynamicChildren = null; + } + let nextNode = null; + switch (type) { + case Text: + if (domType !== 3) { + if (vnode.children === "") { + insert(vnode.el = createText(""), parentNode(node), node); + nextNode = node; + } else { + nextNode = onMismatch(); + } + } else { + if (node.data !== vnode.children) { + warn$1( + `Hydration text mismatch in`, + node.parentNode, + ` + - rendered on server: ${JSON.stringify( + node.data + )} + - expected on client: ${JSON.stringify(vnode.children)}` + ); + logMismatchError(); + node.data = vnode.children; + } + nextNode = nextSibling(node); + } + break; + case Comment: + if (isTemplateNode(node)) { + nextNode = nextSibling(node); + replaceNode( + vnode.el = node.content.firstChild, + node, + parentComponent + ); + } else if (domType !== 8 || isFragmentStart) { + nextNode = onMismatch(); + } else { + nextNode = nextSibling(node); + } + break; + case Static: + if (isFragmentStart) { + node = nextSibling(node); + domType = node.nodeType; + } + if (domType === 1 || domType === 3) { + nextNode = node; + const needToAdoptContent = !vnode.children.length; + for (let i = 0; i < vnode.staticCount; i++) { + if (needToAdoptContent) + vnode.children += nextNode.nodeType === 1 ? nextNode.outerHTML : nextNode.data; + if (i === vnode.staticCount - 1) { + vnode.anchor = nextNode; + } + nextNode = nextSibling(nextNode); + } + return isFragmentStart ? nextSibling(nextNode) : nextNode; + } else { + onMismatch(); + } + break; + case Fragment: + if (!isFragmentStart) { + nextNode = onMismatch(); + } else { + nextNode = hydrateFragment( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + } + break; + default: + if (shapeFlag & 1) { + if ((domType !== 1 || vnode.type.toLowerCase() !== node.tagName.toLowerCase()) && !isTemplateNode(node)) { + nextNode = onMismatch(); + } else { + nextNode = hydrateElement( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + } + } else if (shapeFlag & 6) { + vnode.slotScopeIds = slotScopeIds; + const container = parentNode(node); + if (isFragmentStart) { + nextNode = locateClosingAnchor(node); + } else if (isComment(node) && node.data === "teleport start") { + nextNode = locateClosingAnchor(node, node.data, "teleport end"); + } else { + nextNode = nextSibling(node); + } + mountComponent( + vnode, + container, + null, + parentComponent, + parentSuspense, + getContainerType(container), + optimized + ); + if (isAsyncWrapper(vnode) && !vnode.type.__asyncResolved) { + let subTree; + if (isFragmentStart) { + subTree = createVNode(Fragment); + subTree.anchor = nextNode ? nextNode.previousSibling : container.lastChild; + } else { + subTree = node.nodeType === 3 ? createTextVNode("") : createVNode("div"); + } + subTree.el = node; + vnode.component.subTree = subTree; + } + } else if (shapeFlag & 64) { + if (domType !== 8) { + nextNode = onMismatch(); + } else { + nextNode = vnode.type.hydrate( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + optimized, + rendererInternals, + hydrateChildren + ); + } + } else if (shapeFlag & 128) { + nextNode = vnode.type.hydrate( + node, + vnode, + parentComponent, + parentSuspense, + getContainerType(parentNode(node)), + slotScopeIds, + optimized, + rendererInternals, + hydrateNode + ); + } else if (true) { + warn$1("Invalid HostVNode type:", type, `(${typeof type})`); + } + } + if (ref2 != null) { + setRef(ref2, null, parentSuspense, vnode); + } + return nextNode; + }; + const hydrateElement = (el, vnode, parentComponent, parentSuspense, slotScopeIds, optimized) => { + optimized = optimized || !!vnode.dynamicChildren; + const { type, props, patchFlag, shapeFlag, dirs, transition } = vnode; + const forcePatch = type === "input" || type === "option"; + if (true) { + if (dirs) { + invokeDirectiveHook(vnode, null, parentComponent, "created"); + } + let needCallTransitionHooks = false; + if (isTemplateNode(el)) { + needCallTransitionHooks = needTransition( + null, + // no need check parentSuspense in hydration + transition + ) && parentComponent && parentComponent.vnode.props && parentComponent.vnode.props.appear; + const content = el.content.firstChild; + if (needCallTransitionHooks) { + const cls = content.getAttribute("class"); + if (cls) content.$cls = cls; + transition.beforeEnter(content); + } + replaceNode(content, el, parentComponent); + vnode.el = el = content; + } + if (shapeFlag & 16 && // skip if element has innerHTML / textContent + !(props && (props.innerHTML || props.textContent))) { + let next = hydrateChildren( + el.firstChild, + vnode, + el, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + let hasWarned2 = false; + while (next) { + if (!isMismatchAllowed( + el, + 1 + /* CHILDREN */ + )) { + if (!hasWarned2) { + warn$1( + `Hydration children mismatch on`, + el, + ` +Server rendered element contains more child nodes than client vdom.` + ); + hasWarned2 = true; + } + logMismatchError(); + } + const cur = next; + next = next.nextSibling; + remove2(cur); + } + } else if (shapeFlag & 8) { + let clientText = vnode.children; + if (clientText[0] === "\n" && (el.tagName === "PRE" || el.tagName === "TEXTAREA")) { + clientText = clientText.slice(1); + } + const { textContent } = el; + if (textContent !== clientText && // innerHTML normalize \r\n or \r into a single \n in the DOM + textContent !== clientText.replace(/\r\n|\r/g, "\n")) { + if (!isMismatchAllowed( + el, + 0 + /* TEXT */ + )) { + warn$1( + `Hydration text content mismatch on`, + el, + ` + - rendered on server: ${textContent} + - expected on client: ${clientText}` + ); + logMismatchError(); + } + el.textContent = vnode.children; + } + } + if (props) { + if (true) { + const isCustomElement = el.tagName.includes("-"); + for (const key in props) { + if (// #11189 skip if this node has directives that have created hooks + // as it could have mutated the DOM in any possible way + !(dirs && dirs.some((d) => d.dir.created)) && propHasMismatch(el, key, props[key], vnode, parentComponent)) { + logMismatchError(); + } + if (forcePatch && (key.endsWith("value") || key === "indeterminate") || isOn(key) && !isReservedProp(key) || // force hydrate v-bind with .prop modifiers + key[0] === "." || isCustomElement) { + patchProp2(el, key, null, props[key], void 0, parentComponent); + } + } + } else if (props.onClick) { + patchProp2( + el, + "onClick", + null, + props.onClick, + void 0, + parentComponent + ); + } else if (patchFlag & 4 && isReactive(props.style)) { + for (const key in props.style) props.style[key]; + } + } + let vnodeHooks; + if (vnodeHooks = props && props.onVnodeBeforeMount) { + invokeVNodeHook(vnodeHooks, parentComponent, vnode); + } + if (dirs) { + invokeDirectiveHook(vnode, null, parentComponent, "beforeMount"); + } + if ((vnodeHooks = props && props.onVnodeMounted) || dirs || needCallTransitionHooks) { + queueEffectWithSuspense(() => { + vnodeHooks && invokeVNodeHook(vnodeHooks, parentComponent, vnode); + needCallTransitionHooks && transition.enter(el); + dirs && invokeDirectiveHook(vnode, null, parentComponent, "mounted"); + }, parentSuspense); + } + } + return el.nextSibling; + }; + const hydrateChildren = (node, parentVNode, container, parentComponent, parentSuspense, slotScopeIds, optimized) => { + optimized = optimized || !!parentVNode.dynamicChildren; + const children = parentVNode.children; + const l = children.length; + let hasWarned2 = false; + for (let i = 0; i < l; i++) { + const vnode = optimized ? children[i] : children[i] = normalizeVNode(children[i]); + const isText = vnode.type === Text; + if (node) { + if (isText && !optimized) { + if (i + 1 < l && normalizeVNode(children[i + 1]).type === Text) { + insert( + createText( + node.data.slice(vnode.children.length) + ), + container, + nextSibling(node) + ); + node.data = vnode.children; + } + } + node = hydrateNode( + node, + vnode, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + } else if (isText && !vnode.children) { + insert(vnode.el = createText(""), container); + } else { + if (!isMismatchAllowed( + container, + 1 + /* CHILDREN */ + )) { + if (!hasWarned2) { + warn$1( + `Hydration children mismatch on`, + container, + ` +Server rendered element contains fewer child nodes than client vdom.` + ); + hasWarned2 = true; + } + logMismatchError(); + } + patch( + null, + vnode, + container, + null, + parentComponent, + parentSuspense, + getContainerType(container), + slotScopeIds + ); + } + } + return node; + }; + const hydrateFragment = (node, vnode, parentComponent, parentSuspense, slotScopeIds, optimized) => { + const { slotScopeIds: fragmentSlotScopeIds } = vnode; + if (fragmentSlotScopeIds) { + slotScopeIds = slotScopeIds ? slotScopeIds.concat(fragmentSlotScopeIds) : fragmentSlotScopeIds; + } + const container = parentNode(node); + const next = hydrateChildren( + nextSibling(node), + vnode, + container, + parentComponent, + parentSuspense, + slotScopeIds, + optimized + ); + if (next && isComment(next) && next.data === "]") { + return nextSibling(vnode.anchor = next); + } else { + logMismatchError(); + insert(vnode.anchor = createComment(`]`), container, next); + return next; + } + }; + const handleMismatch = (node, vnode, parentComponent, parentSuspense, slotScopeIds, isFragment) => { + if (!isMismatchAllowed( + node.parentElement, + 1 + /* CHILDREN */ + )) { + warn$1( + `Hydration node mismatch: +- rendered on server:`, + node, + node.nodeType === 3 ? `(text)` : isComment(node) && node.data === "[" ? `(start of fragment)` : ``, + ` +- expected on client:`, + vnode.type + ); + logMismatchError(); + } + vnode.el = null; + if (isFragment) { + const end = locateClosingAnchor(node); + while (true) { + const next2 = nextSibling(node); + if (next2 && next2 !== end) { + remove2(next2); + } else { + break; + } + } + } + const next = nextSibling(node); + const container = parentNode(node); + remove2(node); + patch( + null, + vnode, + container, + next, + parentComponent, + parentSuspense, + getContainerType(container), + slotScopeIds + ); + if (parentComponent) { + parentComponent.vnode.el = vnode.el; + updateHOCHostEl(parentComponent, vnode.el); + } + return next; + }; + const locateClosingAnchor = (node, open = "[", close = "]") => { + let match = 0; + while (node) { + node = nextSibling(node); + if (node && isComment(node)) { + if (node.data === open) match++; + if (node.data === close) { + if (match === 0) { + return nextSibling(node); + } else { + match--; + } + } + } + } + return node; + }; + const replaceNode = (newNode, oldNode, parentComponent) => { + const parentNode2 = oldNode.parentNode; + if (parentNode2) { + parentNode2.replaceChild(newNode, oldNode); + } + let parent = parentComponent; + while (parent) { + if (parent.vnode.el === oldNode) { + parent.vnode.el = parent.subTree.el = newNode; + } + parent = parent.parent; + } + }; + const isTemplateNode = (node) => { + return node.nodeType === 1 && node.tagName === "TEMPLATE"; + }; + return [hydrate2, hydrateNode]; +} +function propHasMismatch(el, key, clientValue, vnode, instance) { + let mismatchType; + let mismatchKey; + let actual; + let expected; + if (key === "class") { + if (el.$cls) { + actual = el.$cls; + delete el.$cls; + } else { + actual = el.getAttribute("class"); + } + expected = normalizeClass(clientValue); + if (!isSetEqual(toClassSet(actual || ""), toClassSet(expected))) { + mismatchType = 2; + mismatchKey = `class`; + } + } else if (key === "style") { + actual = el.getAttribute("style") || ""; + expected = isString(clientValue) ? clientValue : stringifyStyle(normalizeStyle(clientValue)); + const actualMap = toStyleMap(actual); + const expectedMap = toStyleMap(expected); + if (vnode.dirs) { + for (const { dir, value } of vnode.dirs) { + if (dir.name === "show" && !value) { + expectedMap.set("display", "none"); + } + } + } + if (instance) { + resolveCssVars(instance, vnode, expectedMap); + } + if (!isMapEqual(actualMap, expectedMap)) { + mismatchType = 3; + mismatchKey = "style"; + } + } else if (el instanceof SVGElement && isKnownSvgAttr(key) || el instanceof HTMLElement && (isBooleanAttr(key) || isKnownHtmlAttr(key))) { + if (isBooleanAttr(key)) { + actual = el.hasAttribute(key); + expected = includeBooleanAttr(clientValue); + } else if (clientValue == null) { + actual = el.hasAttribute(key); + expected = false; + } else { + if (el.hasAttribute(key)) { + actual = el.getAttribute(key); + } else if (key === "value" && el.tagName === "TEXTAREA") { + actual = el.value; + } else { + actual = false; + } + expected = isRenderableAttrValue(clientValue) ? String(clientValue) : false; + } + if (actual !== expected) { + mismatchType = 4; + mismatchKey = key; + } + } + if (mismatchType != null && !isMismatchAllowed(el, mismatchType)) { + const format = (v) => v === false ? `(not rendered)` : `${mismatchKey}="${v}"`; + const preSegment = `Hydration ${MismatchTypeString[mismatchType]} mismatch on`; + const postSegment = ` + - rendered on server: ${format(actual)} + - expected on client: ${format(expected)} + Note: this mismatch is check-only. The DOM will not be rectified in production due to performance overhead. + You should fix the source of the mismatch.`; + { + warn$1(preSegment, el, postSegment); + } + return true; + } + return false; +} +function toClassSet(str) { + return new Set(str.trim().split(/\s+/)); +} +function isSetEqual(a, b) { + if (a.size !== b.size) { + return false; + } + for (const s of a) { + if (!b.has(s)) { + return false; + } + } + return true; +} +function toStyleMap(str) { + const styleMap = /* @__PURE__ */ new Map(); + for (const item of str.split(";")) { + let [key, value] = item.split(":"); + key = key.trim(); + value = value && value.trim(); + if (key && value) { + styleMap.set(key, value); + } + } + return styleMap; +} +function isMapEqual(a, b) { + if (a.size !== b.size) { + return false; + } + for (const [key, value] of a) { + if (value !== b.get(key)) { + return false; + } + } + return true; +} +function resolveCssVars(instance, vnode, expectedMap) { + const root = instance.subTree; + if (instance.getCssVars && (vnode === root || root && root.type === Fragment && root.children.includes(vnode))) { + const cssVars = instance.getCssVars(); + for (const key in cssVars) { + const value = normalizeCssVarValue(cssVars[key]); + expectedMap.set(`--${getEscapedCssVarName(key, false)}`, value); + } + } + if (vnode === root && instance.parent) { + resolveCssVars(instance.parent, instance.vnode, expectedMap); + } +} +var allowMismatchAttr = "data-allow-mismatch"; +var MismatchTypeString = { + [ + 0 + /* TEXT */ + ]: "text", + [ + 1 + /* CHILDREN */ + ]: "children", + [ + 2 + /* CLASS */ + ]: "class", + [ + 3 + /* STYLE */ + ]: "style", + [ + 4 + /* ATTRIBUTE */ + ]: "attribute" +}; +function isMismatchAllowed(el, allowedType) { + if (allowedType === 0 || allowedType === 1) { + while (el && !el.hasAttribute(allowMismatchAttr)) { + el = el.parentElement; + } + } + const allowedAttr = el && el.getAttribute(allowMismatchAttr); + if (allowedAttr == null) { + return false; + } else if (allowedAttr === "") { + return true; + } else { + const list = allowedAttr.split(","); + if (allowedType === 0 && list.includes("children")) { + return true; + } + return list.includes(MismatchTypeString[allowedType]); + } +} +var requestIdleCallback = getGlobalThis().requestIdleCallback || ((cb) => setTimeout(cb, 1)); +var cancelIdleCallback = getGlobalThis().cancelIdleCallback || ((id) => clearTimeout(id)); +var hydrateOnIdle = (timeout = 1e4) => (hydrate2) => { + const id = requestIdleCallback(hydrate2, { timeout }); + return () => cancelIdleCallback(id); +}; +function elementIsVisibleInViewport(el) { + const { top, left, bottom, right } = el.getBoundingClientRect(); + const { innerHeight, innerWidth } = window; + return (top > 0 && top < innerHeight || bottom > 0 && bottom < innerHeight) && (left > 0 && left < innerWidth || right > 0 && right < innerWidth); +} +var hydrateOnVisible = (opts) => (hydrate2, forEach) => { + const ob = new IntersectionObserver((entries) => { + for (const e of entries) { + if (!e.isIntersecting) continue; + ob.disconnect(); + hydrate2(); + break; + } + }, opts); + forEach((el) => { + if (!(el instanceof Element)) return; + if (elementIsVisibleInViewport(el)) { + hydrate2(); + ob.disconnect(); + return false; + } + ob.observe(el); + }); + return () => ob.disconnect(); +}; +var hydrateOnMediaQuery = (query) => (hydrate2) => { + if (query) { + const mql = matchMedia(query); + if (mql.matches) { + hydrate2(); + } else { + mql.addEventListener("change", hydrate2, { once: true }); + return () => mql.removeEventListener("change", hydrate2); + } + } +}; +var hydrateOnInteraction = (interactions = []) => (hydrate2, forEach) => { + if (isString(interactions)) interactions = [interactions]; + let hasHydrated = false; + const doHydrate = (e) => { + if (!hasHydrated) { + hasHydrated = true; + teardown(); + hydrate2(); + e.target.dispatchEvent(new e.constructor(e.type, e)); + } + }; + const teardown = () => { + forEach((el) => { + for (const i of interactions) { + el.removeEventListener(i, doHydrate); + } + }); + }; + forEach((el) => { + for (const i of interactions) { + el.addEventListener(i, doHydrate, { once: true }); + } + }); + return teardown; +}; +function forEachElement(node, cb) { + if (isComment(node) && node.data === "[") { + let depth = 1; + let next = node.nextSibling; + while (next) { + if (next.nodeType === 1) { + const result = cb(next); + if (result === false) { + break; + } + } else if (isComment(next)) { + if (next.data === "]") { + if (--depth === 0) break; + } else if (next.data === "[") { + depth++; + } + } + next = next.nextSibling; + } + } else { + cb(node); + } +} +var isAsyncWrapper = (i) => !!i.type.__asyncLoader; +function defineAsyncComponent(source) { + if (isFunction(source)) { + source = { loader: source }; + } + const { + loader, + loadingComponent, + errorComponent, + delay = 200, + hydrate: hydrateStrategy, + timeout, + // undefined = never times out + suspensible = true, + onError: userOnError + } = source; + let pendingRequest = null; + let resolvedComp; + let retries = 0; + const retry = () => { + retries++; + pendingRequest = null; + return load(); + }; + const load = () => { + let thisRequest; + return pendingRequest || (thisRequest = pendingRequest = loader().catch((err) => { + err = err instanceof Error ? err : new Error(String(err)); + if (userOnError) { + return new Promise((resolve2, reject) => { + const userRetry = () => resolve2(retry()); + const userFail = () => reject(err); + userOnError(err, userRetry, userFail, retries + 1); + }); + } else { + throw err; + } + }).then((comp) => { + if (thisRequest !== pendingRequest && pendingRequest) { + return pendingRequest; + } + if (!comp) { + warn$1( + `Async component loader resolved to undefined. If you are using retry(), make sure to return its return value.` + ); + } + if (comp && (comp.__esModule || comp[Symbol.toStringTag] === "Module")) { + comp = comp.default; + } + if (comp && !isObject(comp) && !isFunction(comp)) { + throw new Error(`Invalid async component load result: ${comp}`); + } + resolvedComp = comp; + return comp; + })); + }; + return defineComponent({ + name: "AsyncComponentWrapper", + __asyncLoader: load, + __asyncHydrate(el, instance, hydrate2) { + let patched = false; + (instance.bu || (instance.bu = [])).push(() => patched = true); + const performHydrate = () => { + if (patched) { + if (true) { + warn$1( + `Skipping lazy hydration for component '${getComponentName(resolvedComp) || resolvedComp.__file}': it was updated before lazy hydration performed.` + ); + } + return; + } + hydrate2(); + }; + const doHydrate = hydrateStrategy ? () => { + const teardown = hydrateStrategy( + performHydrate, + (cb) => forEachElement(el, cb) + ); + if (teardown) { + (instance.bum || (instance.bum = [])).push(teardown); + } + } : performHydrate; + if (resolvedComp) { + doHydrate(); + } else { + load().then(() => !instance.isUnmounted && doHydrate()); + } + }, + get __asyncResolved() { + return resolvedComp; + }, + setup() { + const instance = currentInstance; + markAsyncBoundary(instance); + if (resolvedComp) { + return () => createInnerComp(resolvedComp, instance); + } + const onError = (err) => { + pendingRequest = null; + handleError( + err, + instance, + 13, + !errorComponent + ); + }; + if (suspensible && instance.suspense || isInSSRComponentSetup) { + return load().then((comp) => { + return () => createInnerComp(comp, instance); + }).catch((err) => { + onError(err); + return () => errorComponent ? createVNode(errorComponent, { + error: err + }) : null; + }); + } + const loaded = ref(false); + const error = ref(); + const delayed = ref(!!delay); + if (delay) { + setTimeout(() => { + delayed.value = false; + }, delay); + } + if (timeout != null) { + setTimeout(() => { + if (!loaded.value && !error.value) { + const err = new Error( + `Async component timed out after ${timeout}ms.` + ); + onError(err); + error.value = err; + } + }, timeout); + } + load().then(() => { + loaded.value = true; + if (instance.parent && isKeepAlive(instance.parent.vnode)) { + instance.parent.update(); + } + }).catch((err) => { + onError(err); + error.value = err; + }); + return () => { + if (loaded.value && resolvedComp) { + return createInnerComp(resolvedComp, instance); + } else if (error.value && errorComponent) { + return createVNode(errorComponent, { + error: error.value + }); + } else if (loadingComponent && !delayed.value) { + return createInnerComp( + loadingComponent, + instance + ); + } + }; + } + }); +} +function createInnerComp(comp, parent) { + const { ref: ref2, props, children, ce } = parent.vnode; + const vnode = createVNode(comp, props, children); + vnode.ref = ref2; + vnode.ce = ce; + delete parent.vnode.ce; + return vnode; +} +var isKeepAlive = (vnode) => vnode.type.__isKeepAlive; +var KeepAliveImpl = { + name: `KeepAlive`, + // Marker for special handling inside the renderer. We are not using a === + // check directly on KeepAlive in the renderer, because importing it directly + // would prevent it from being tree-shaken. + __isKeepAlive: true, + props: { + include: [String, RegExp, Array], + exclude: [String, RegExp, Array], + max: [String, Number] + }, + setup(props, { slots }) { + const instance = getCurrentInstance(); + const sharedContext = instance.ctx; + if (!sharedContext.renderer) { + return () => { + const children = slots.default && slots.default(); + return children && children.length === 1 ? children[0] : children; + }; + } + const cache = /* @__PURE__ */ new Map(); + const keys = /* @__PURE__ */ new Set(); + let current = null; + if (true) { + instance.__v_cache = cache; + } + const parentSuspense = instance.suspense; + const { + renderer: { + p: patch, + m: move, + um: _unmount, + o: { createElement } + } + } = sharedContext; + const storageContainer = createElement("div"); + sharedContext.activate = (vnode, container, anchor, namespace, optimized) => { + const instance2 = vnode.component; + move(vnode, container, anchor, 0, parentSuspense); + patch( + instance2.vnode, + vnode, + container, + anchor, + instance2, + parentSuspense, + namespace, + vnode.slotScopeIds, + optimized + ); + queuePostRenderEffect(() => { + instance2.isDeactivated = false; + if (instance2.a) { + invokeArrayFns(instance2.a); + } + const vnodeHook = vnode.props && vnode.props.onVnodeMounted; + if (vnodeHook) { + invokeVNodeHook(vnodeHook, instance2.parent, vnode); + } + }, parentSuspense); + if (true) { + devtoolsComponentAdded(instance2); + } + }; + sharedContext.deactivate = (vnode) => { + const instance2 = vnode.component; + invalidateMount(instance2.m); + invalidateMount(instance2.a); + move(vnode, storageContainer, null, 1, parentSuspense); + queuePostRenderEffect(() => { + if (instance2.da) { + invokeArrayFns(instance2.da); + } + const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted; + if (vnodeHook) { + invokeVNodeHook(vnodeHook, instance2.parent, vnode); + } + instance2.isDeactivated = true; + }, parentSuspense); + if (true) { + devtoolsComponentAdded(instance2); + } + if (true) { + instance2.__keepAliveStorageContainer = storageContainer; + } + }; + function unmount(vnode) { + resetShapeFlag(vnode); + _unmount(vnode, instance, parentSuspense, true); + } + function pruneCache(filter) { + cache.forEach((vnode, key) => { + const name = getComponentName( + isAsyncWrapper(vnode) ? vnode.type.__asyncResolved || {} : vnode.type + ); + if (name && !filter(name)) { + pruneCacheEntry(key); + } + }); + } + function pruneCacheEntry(key) { + const cached = cache.get(key); + if (cached && (!current || !isSameVNodeType(cached, current))) { + unmount(cached); + } else if (current) { + resetShapeFlag(current); + } + cache.delete(key); + keys.delete(key); + } + watch2( + () => [props.include, props.exclude], + ([include, exclude]) => { + include && pruneCache((name) => matches(include, name)); + exclude && pruneCache((name) => !matches(exclude, name)); + }, + // prune post-render after `current` has been updated + { flush: "post", deep: true } + ); + let pendingCacheKey = null; + const cacheSubtree = () => { + if (pendingCacheKey != null) { + if (isSuspense(instance.subTree.type)) { + queuePostRenderEffect(() => { + cache.set(pendingCacheKey, getInnerChild(instance.subTree)); + }, instance.subTree.suspense); + } else { + cache.set(pendingCacheKey, getInnerChild(instance.subTree)); + } + } + }; + onMounted(cacheSubtree); + onUpdated(cacheSubtree); + onBeforeUnmount(() => { + cache.forEach((cached) => { + const { subTree, suspense } = instance; + const vnode = getInnerChild(subTree); + if (cached.type === vnode.type && cached.key === vnode.key) { + resetShapeFlag(vnode); + const da = vnode.component.da; + da && queuePostRenderEffect(da, suspense); + return; + } + unmount(cached); + }); + }); + return () => { + pendingCacheKey = null; + if (!slots.default) { + return current = null; + } + const children = slots.default(); + const rawVNode = children[0]; + if (children.length > 1) { + if (true) { + warn$1(`KeepAlive should contain exactly one component child.`); + } + current = null; + return children; + } else if (!isVNode(rawVNode) || !(rawVNode.shapeFlag & 4) && !(rawVNode.shapeFlag & 128)) { + current = null; + return rawVNode; + } + let vnode = getInnerChild(rawVNode); + if (vnode.type === Comment) { + current = null; + return vnode; + } + const comp = vnode.type; + const name = getComponentName( + isAsyncWrapper(vnode) ? vnode.type.__asyncResolved || {} : comp + ); + const { include, exclude, max } = props; + if (include && (!name || !matches(include, name)) || exclude && name && matches(exclude, name)) { + vnode.shapeFlag &= -257; + current = vnode; + return rawVNode; + } + const key = vnode.key == null ? comp : vnode.key; + const cachedVNode = cache.get(key); + if (vnode.el) { + vnode = cloneVNode(vnode); + if (rawVNode.shapeFlag & 128) { + rawVNode.ssContent = vnode; + } + } + pendingCacheKey = key; + if (cachedVNode) { + vnode.el = cachedVNode.el; + vnode.component = cachedVNode.component; + if (vnode.transition) { + setTransitionHooks(vnode, vnode.transition); + } + vnode.shapeFlag |= 512; + keys.delete(key); + keys.add(key); + } else { + keys.add(key); + if (max && keys.size > parseInt(max, 10)) { + pruneCacheEntry(keys.values().next().value); + } + } + vnode.shapeFlag |= 256; + current = vnode; + return isSuspense(rawVNode.type) ? rawVNode : vnode; + }; + } +}; +var KeepAlive = KeepAliveImpl; +function matches(pattern, name) { + if (isArray(pattern)) { + return pattern.some((p2) => matches(p2, name)); + } else if (isString(pattern)) { + return pattern.split(",").includes(name); + } else if (isRegExp(pattern)) { + pattern.lastIndex = 0; + return pattern.test(name); + } + return false; +} +function onActivated(hook, target) { + registerKeepAliveHook(hook, "a", target); +} +function onDeactivated(hook, target) { + registerKeepAliveHook(hook, "da", target); +} +function registerKeepAliveHook(hook, type, target = currentInstance) { + const wrappedHook = hook.__wdc || (hook.__wdc = () => { + let current = target; + while (current) { + if (current.isDeactivated) { + return; + } + current = current.parent; + } + return hook(); + }); + injectHook(type, wrappedHook, target); + if (target) { + let current = target.parent; + while (current && current.parent) { + if (isKeepAlive(current.parent.vnode)) { + injectToKeepAliveRoot(wrappedHook, type, target, current); + } + current = current.parent; + } + } +} +function injectToKeepAliveRoot(hook, type, target, keepAliveRoot) { + const injected = injectHook( + type, + hook, + keepAliveRoot, + true + /* prepend */ + ); + onUnmounted(() => { + remove(keepAliveRoot[type], injected); + }, target); +} +function resetShapeFlag(vnode) { + vnode.shapeFlag &= -257; + vnode.shapeFlag &= -513; +} +function getInnerChild(vnode) { + return vnode.shapeFlag & 128 ? vnode.ssContent : vnode; +} +function injectHook(type, hook, target = currentInstance, prepend = false) { + if (target) { + const hooks = target[type] || (target[type] = []); + const wrappedHook = hook.__weh || (hook.__weh = (...args) => { + pauseTracking(); + const reset = setCurrentInstance(target); + const res = callWithAsyncErrorHandling(hook, target, type, args); + reset(); + resetTracking(); + return res; + }); + if (prepend) { + hooks.unshift(wrappedHook); + } else { + hooks.push(wrappedHook); + } + return wrappedHook; + } else if (true) { + const apiName = toHandlerKey(ErrorTypeStrings$1[type].replace(/ hook$/, "")); + warn$1( + `${apiName} is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup(). If you are using async setup(), make sure to register lifecycle hooks before the first await statement.` + ); + } +} +var createHook = (lifecycle) => (hook, target = currentInstance) => { + if (!isInSSRComponentSetup || lifecycle === "sp") { + injectHook(lifecycle, (...args) => hook(...args), target); + } +}; +var onBeforeMount = createHook("bm"); +var onMounted = createHook("m"); +var onBeforeUpdate = createHook( + "bu" +); +var onUpdated = createHook("u"); +var onBeforeUnmount = createHook( + "bum" +); +var onUnmounted = createHook("um"); +var onServerPrefetch = createHook( + "sp" +); +var onRenderTriggered = createHook("rtg"); +var onRenderTracked = createHook("rtc"); +function onErrorCaptured(hook, target = currentInstance) { + injectHook("ec", hook, target); +} +var COMPONENTS = "components"; +var DIRECTIVES = "directives"; +function resolveComponent(name, maybeSelfReference) { + return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name; +} +var NULL_DYNAMIC_COMPONENT = Symbol.for("v-ndc"); +function resolveDynamicComponent(component) { + if (isString(component)) { + return resolveAsset(COMPONENTS, component, false) || component; + } else { + return component || NULL_DYNAMIC_COMPONENT; + } +} +function resolveDirective(name) { + return resolveAsset(DIRECTIVES, name); +} +function resolveAsset(type, name, warnMissing = true, maybeSelfReference = false) { + const instance = currentRenderingInstance || currentInstance; + if (instance) { + const Component = instance.type; + if (type === COMPONENTS) { + const selfName = getComponentName( + Component, + false + ); + if (selfName && (selfName === name || selfName === camelize(name) || selfName === capitalize(camelize(name)))) { + return Component; + } + } + const res = ( + // local registration + // check instance[type] first which is resolved for options API + resolve(instance[type] || Component[type], name) || // global registration + resolve(instance.appContext[type], name) + ); + if (!res && maybeSelfReference) { + return Component; + } + if (warnMissing && !res) { + const extra = type === COMPONENTS ? ` +If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.` : ``; + warn$1(`Failed to resolve ${type.slice(0, -1)}: ${name}${extra}`); + } + return res; + } else if (true) { + warn$1( + `resolve${capitalize(type.slice(0, -1))} can only be used in render() or setup().` + ); + } +} +function resolve(registry, name) { + return registry && (registry[name] || registry[camelize(name)] || registry[capitalize(camelize(name))]); +} +function renderList(source, renderItem, cache, index) { + let ret; + const cached = cache && cache[index]; + const sourceIsArray = isArray(source); + if (sourceIsArray || isString(source)) { + const sourceIsReactiveArray = sourceIsArray && isReactive(source); + let needsWrap = false; + let isReadonlySource = false; + if (sourceIsReactiveArray) { + needsWrap = !isShallow(source); + isReadonlySource = isReadonly(source); + source = shallowReadArray(source); + } + ret = new Array(source.length); + for (let i = 0, l = source.length; i < l; i++) { + ret[i] = renderItem( + needsWrap ? isReadonlySource ? toReadonly(toReactive(source[i])) : toReactive(source[i]) : source[i], + i, + void 0, + cached && cached[i] + ); + } + } else if (typeof source === "number") { + if (!Number.isInteger(source)) { + warn$1(`The v-for range expect an integer value but got ${source}.`); + } + ret = new Array(source); + for (let i = 0; i < source; i++) { + ret[i] = renderItem(i + 1, i, void 0, cached && cached[i]); + } + } else if (isObject(source)) { + if (source[Symbol.iterator]) { + ret = Array.from( + source, + (item, i) => renderItem(item, i, void 0, cached && cached[i]) + ); + } else { + const keys = Object.keys(source); + ret = new Array(keys.length); + for (let i = 0, l = keys.length; i < l; i++) { + const key = keys[i]; + ret[i] = renderItem(source[key], key, i, cached && cached[i]); + } + } + } else { + ret = []; + } + if (cache) { + cache[index] = ret; + } + return ret; +} +function createSlots(slots, dynamicSlots) { + for (let i = 0; i < dynamicSlots.length; i++) { + const slot = dynamicSlots[i]; + if (isArray(slot)) { + for (let j = 0; j < slot.length; j++) { + slots[slot[j].name] = slot[j].fn; + } + } else if (slot) { + slots[slot.name] = slot.key ? (...args) => { + const res = slot.fn(...args); + if (res) res.key = slot.key; + return res; + } : slot.fn; + } + } + return slots; +} +function renderSlot(slots, name, props = {}, fallback, noSlotted) { + if (currentRenderingInstance.ce || currentRenderingInstance.parent && isAsyncWrapper(currentRenderingInstance.parent) && currentRenderingInstance.parent.ce) { + const hasProps = Object.keys(props).length > 0; + if (name !== "default") props.name = name; + return openBlock(), createBlock( + Fragment, + null, + [createVNode("slot", props, fallback && fallback())], + hasProps ? -2 : 64 + ); + } + let slot = slots[name]; + if (slot && slot.length > 1) { + warn$1( + `SSR-optimized slot function detected in a non-SSR-optimized render function. You need to mark this component with $dynamic-slots in the parent template.` + ); + slot = () => []; + } + if (slot && slot._c) { + slot._d = false; + } + openBlock(); + const validSlotContent = slot && ensureValidVNode(slot(props)); + const slotKey = props.key || // slot content array of a dynamic conditional slot may have a branch + // key attached in the `createSlots` helper, respect that + validSlotContent && validSlotContent.key; + const rendered = createBlock( + Fragment, + { + key: (slotKey && !isSymbol(slotKey) ? slotKey : `_${name}`) + // #7256 force differentiate fallback content from actual content + (!validSlotContent && fallback ? "_fb" : "") + }, + validSlotContent || (fallback ? fallback() : []), + validSlotContent && slots._ === 1 ? 64 : -2 + ); + if (!noSlotted && rendered.scopeId) { + rendered.slotScopeIds = [rendered.scopeId + "-s"]; + } + if (slot && slot._c) { + slot._d = true; + } + return rendered; +} +function ensureValidVNode(vnodes) { + return vnodes.some((child) => { + if (!isVNode(child)) return true; + if (child.type === Comment) return false; + if (child.type === Fragment && !ensureValidVNode(child.children)) + return false; + return true; + }) ? vnodes : null; +} +function toHandlers(obj, preserveCaseIfNecessary) { + const ret = {}; + if (!isObject(obj)) { + warn$1(`v-on with no argument expects an object value.`); + return ret; + } + for (const key in obj) { + ret[preserveCaseIfNecessary && /[A-Z]/.test(key) ? `on:${key}` : toHandlerKey(key)] = obj[key]; + } + return ret; +} +var getPublicInstance = (i) => { + if (!i) return null; + if (isStatefulComponent(i)) return getComponentPublicInstance(i); + return getPublicInstance(i.parent); +}; +var publicPropertiesMap = ( + // Move PURE marker to new line to workaround compiler discarding it + // due to type annotation + extend(/* @__PURE__ */ Object.create(null), { + $: (i) => i, + $el: (i) => i.vnode.el, + $data: (i) => i.data, + $props: (i) => true ? shallowReadonly(i.props) : i.props, + $attrs: (i) => true ? shallowReadonly(i.attrs) : i.attrs, + $slots: (i) => true ? shallowReadonly(i.slots) : i.slots, + $refs: (i) => true ? shallowReadonly(i.refs) : i.refs, + $parent: (i) => getPublicInstance(i.parent), + $root: (i) => getPublicInstance(i.root), + $host: (i) => i.ce, + $emit: (i) => i.emit, + $options: (i) => __VUE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type, + $forceUpdate: (i) => i.f || (i.f = () => { + queueJob(i.update); + }), + $nextTick: (i) => i.n || (i.n = nextTick.bind(i.proxy)), + $watch: (i) => __VUE_OPTIONS_API__ ? instanceWatch.bind(i) : NOOP + }) +); +var isReservedPrefix = (key) => key === "_" || key === "$"; +var hasSetupBinding = (state, key) => state !== EMPTY_OBJ && !state.__isScriptSetup && hasOwn(state, key); +var PublicInstanceProxyHandlers = { + get({ _: instance }, key) { + if (key === "__v_skip") { + return true; + } + const { ctx, setupState, data, props, accessCache, type, appContext } = instance; + if (key === "__isVue") { + return true; + } + if (key[0] !== "$") { + const n = accessCache[key]; + if (n !== void 0) { + switch (n) { + case 1: + return setupState[key]; + case 2: + return data[key]; + case 4: + return ctx[key]; + case 3: + return props[key]; + } + } else if (hasSetupBinding(setupState, key)) { + accessCache[key] = 1; + return setupState[key]; + } else if (__VUE_OPTIONS_API__ && data !== EMPTY_OBJ && hasOwn(data, key)) { + accessCache[key] = 2; + return data[key]; + } else if (hasOwn(props, key)) { + accessCache[key] = 3; + return props[key]; + } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { + accessCache[key] = 4; + return ctx[key]; + } else if (!__VUE_OPTIONS_API__ || shouldCacheAccess) { + accessCache[key] = 0; + } + } + const publicGetter = publicPropertiesMap[key]; + let cssModule, globalProperties; + if (publicGetter) { + if (key === "$attrs") { + track(instance.attrs, "get", ""); + markAttrsAccessed(); + } else if (key === "$slots") { + track(instance, "get", key); + } + return publicGetter(instance); + } else if ( + // css module (injected by vue-loader) + (cssModule = type.__cssModules) && (cssModule = cssModule[key]) + ) { + return cssModule; + } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { + accessCache[key] = 4; + return ctx[key]; + } else if ( + // global properties + globalProperties = appContext.config.globalProperties, hasOwn(globalProperties, key) + ) { + { + return globalProperties[key]; + } + } else if (currentRenderingInstance && (!isString(key) || // #1091 avoid internal isRef/isVNode checks on component instance leading + // to infinite warning loop + key.indexOf("__v") !== 0)) { + if (data !== EMPTY_OBJ && isReservedPrefix(key[0]) && hasOwn(data, key)) { + warn$1( + `Property ${JSON.stringify( + key + )} must be accessed via $data because it starts with a reserved character ("$" or "_") and is not proxied on the render context.` + ); + } else if (instance === currentRenderingInstance) { + warn$1( + `Property ${JSON.stringify(key)} was accessed during render but is not defined on instance.` + ); + } + } + }, + set({ _: instance }, key, value) { + const { data, setupState, ctx } = instance; + if (hasSetupBinding(setupState, key)) { + setupState[key] = value; + return true; + } else if (setupState.__isScriptSetup && hasOwn(setupState, key)) { + warn$1(`Cannot mutate - - - - + {{> footer }} - \ No newline at end of file + + + + + + + diff --git a/index.html b/index.html index aabe323..b2c6ddc 100644 --- a/index.html +++ b/index.html @@ -1,934 +1,1397 @@ + + + - - - - BentoPDF - The Privacy First PDF Toolkit - - - - - - - - - - - + + BentoPDF - Free Online PDF Tools | Privacy-First PDF Toolkit + + + + + - - -
-
-
-

- The - PDF Toolkit built - for - privacy. -

- -
- - - No Signups + + + + + + + + + + + + + + + + + + + + + {{> navbar }} + + +
+
+ + Love BentoPDF? Help us keep it free and open source! - - - Unlimited Use - - - - Works Offline - -
- - -
+
- -
-
-

Used by companies and - people working at

+
+
+
+

+ The + + PDF Toolkit + + + built for privacy. +

+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- -
- -
-

- BentoPDF? -

-
-
-
- -

No Signup

-
-

- Start instantly, no accounts or emails. -

-
-
-
- -

No Uploads

-
-

- 100% client-side, your files never leave your device. -

-
-
-
- -

Forever Free

-
-

- All tools, no trials, no paywalls. -

-
-
-
- -

No Limits

-
-

- Use as much as you want, no hidden caps. -

-
-
-
- -

Batch Processing

-
-

Handle unlimited PDFs in one - go. -

-
-
-
- -

Lightning Fast

-
-

- Process PDFs instantly, without waiting or delays. -

-
-
-
- -
- -
-

- Get Started with Tools -

-

Click a tool to open the file uploader

-
- -
-
-
- - + class="flex flex-wrap justify-center items-center gap-2 sm:gap-4 mb-12 mt-12" + > + + + No Signups - - - - + + + Unlimited Use + + + + Works Offline
-
-
-
+ + - + +
+
+

+ Used by companies and people working at +

+
+ + + + - +
+ +
+ +
+

+ + BentoPDF? +

+
+
+
+ +

+ No Signup +

+
+

+ Start instantly, no accounts or emails. +

+
+
+
+ +

+ No Uploads +

+
+

+ 100% client-side, your files never leave your device. +

+
+
+
+ +

+ Forever Free +

+
+

+ All tools, no trials, no paywalls. +

+
+
+
+ +

+ No Limits +

+
+

+ Use as much as you want, no hidden caps. +

+
+
+
+ +

+ Batch Processing +

+
+

+ Handle unlimited PDFs in one go. +

+
+
+
+ +

+ Lightning Fast +

+
+

+ Process PDFs instantly, without waiting or delays. +

+
+
+
+ +
+ +
+

+ Get Started with + + Tools +

+

+ Click a tool to open the file uploader

-
- + +
+
+ + - - - + {{> footer }} - - - - \ No newline at end of file + + + + diff --git a/nginx-ipv6.sh b/nginx-ipv6.sh new file mode 100644 index 0000000..f2a5ee5 --- /dev/null +++ b/nginx-ipv6.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# @see: https://github.com/nginx/docker-nginx-unprivileged/tree/main/stable/alpine-slim + +set -e + +entrypoint_log() { + if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then + echo "$@" + fi +} + +if [ "$DISABLE_IPV6" = "true" ]; then + entrypoint_log "Disabling the Nginx IPv6 listener" + sed -i '/^[[:space:]]*listen[[:space:]]*\[::\]:[0-9]*/s/^/#/' /etc/nginx/nginx.conf +fi + +exit 0 diff --git a/nginx.conf b/nginx.conf index 23dc8a7..d832721 100644 --- a/nginx.conf +++ b/nginx.conf @@ -11,10 +11,13 @@ http { } default_type application/octet-stream; + gzip_static on; + gzip on; gzip_vary on; gzip_min_length 1024; - gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json; + gzip_comp_level 9; + gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json application/wasm application/x-javascript text/x-component; server { listen 8080; @@ -23,21 +26,92 @@ http { root /usr/share/nginx/html; index index.html; - rewrite ^/(en|de|zh|vi)/(.*)$ /$2 last; + + location ~* \.html$ { + expires 1h; + add_header Cache-Control "public, must-revalidate"; + add_header Cross-Origin-Embedder-Policy "require-corp" always; + add_header Cross-Origin-Opener-Policy "same-origin" always; + } + + location ~* /libreoffice-wasm/soffice\.wasm\.gz$ { + gzip off; + types {} default_type application/wasm; + add_header Content-Encoding gzip; + add_header Vary "Accept-Encoding"; + add_header Cache-Control "public, immutable"; + add_header Cross-Origin-Embedder-Policy "require-corp" always; + add_header Cross-Origin-Opener-Policy "same-origin" always; + } + + location ~* /libreoffice-wasm/soffice\.data\.gz$ { + gzip off; + types {} default_type application/octet-stream; + add_header Content-Encoding gzip; + add_header Vary "Accept-Encoding"; + add_header Cache-Control "public, immutable"; + add_header Cross-Origin-Embedder-Policy "require-corp" always; + add_header Cross-Origin-Opener-Policy "same-origin" always; + } + + location ~* \.(wasm|wasm\.gz|data|data\.gz)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + add_header Cross-Origin-Embedder-Policy "require-corp" always; + add_header Cross-Origin-Opener-Policy "same-origin" always; + } + + location ~* \.(js|mjs|css|woff|woff2|ttf|eot|otf)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + add_header Cross-Origin-Embedder-Policy "require-corp" always; + add_header Cross-Origin-Opener-Policy "same-origin" always; + } + + location ~* \.(png|jpg|jpeg|gif|ico|svg|webp|avif|mp4|webm)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + location ~* \.json$ { + expires 1w; + add_header Cache-Control "public, must-revalidate"; + } + + location ~* \.pdf$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + location ~ ^/(en|de|es|zh|zh-TW|vi|it|id|tr|fr|pt)(/.*)?$ { + try_files $uri $uri/ $uri.html /$1/index.html /index.html; + expires 5m; + add_header Cache-Control "public, must-revalidate"; + add_header Cross-Origin-Embedder-Policy "require-corp" always; + add_header Cross-Origin-Opener-Policy "same-origin" always; + } + + location ~ ^/(.+?)/(en|de|es|zh|zh-TW|vi|it|id|tr|fr|pt)(/.*)?$ { + try_files $uri $uri/ $uri.html /$1/$2/index.html /$1/index.html /index.html; + expires 5m; + add_header Cache-Control "public, must-revalidate"; + add_header Cross-Origin-Embedder-Policy "require-corp" always; + add_header Cross-Origin-Opener-Policy "same-origin" always; + } location / { try_files $uri $uri/ $uri.html /index.html; - } - - location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { - expires 1y; - add_header Cache-Control "public, immutable"; + expires 5m; + add_header Cache-Control "public, must-revalidate"; + add_header Cross-Origin-Embedder-Policy "require-corp" always; + add_header Cross-Origin-Opener-Policy "same-origin" always; } add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Cross-Origin-Opener-Policy "same-origin" always; + add_header Cross-Origin-Embedder-Policy "require-corp" always; add_header Cross-Origin-Resource-Policy "cross-origin" always; } } diff --git a/package-lock.json b/package-lock.json index f3e394e..80dae04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,16 @@ { "name": "bento-pdf", - "version": "1.11.2", + "version": "1.15.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "bento-pdf", - "version": "1.11.2", - "license": "Apache-2.0", + "version": "1.15.4", + "license": "AGPL-3.0-only", "dependencies": { + "@bentopdf/gs-wasm": "^0.1.0", + "@bentopdf/pymupdf-wasm": "^0.11.12", "@fontsource/cedarville-cursive": "^5.2.7", "@fontsource/dancing-script": "^5.2.8", "@fontsource/dm-sans": "^5.2.8", @@ -16,32 +18,60 @@ "@fontsource/kalam": "^5.2.8", "@fontsource/lato": "^5.2.7", "@fontsource/merriweather": "^5.2.11", + "@kenjiuno/msgreader": "^1.27.1-alpha.1", + "@matbee/libreoffice-converter": "^2.3.1", "@neslinesli93/qpdf-wasm": "^0.3.0", "@pdf-lib/fontkit": "^1.1.1", + "@phosphor-icons/web": "^2.1.2", "@tailwindcss/vite": "^4.1.15", + "@types/markdown-it": "^14.1.2", + "@types/node-forge": "^1.3.14", + "@types/papaparse": "^5.5.2", "archiver": "^7.0.1", "blob-stream": "^0.1.3", "cropperjs": "^1.6.1", "embedpdf-snippet": "file:vendor/embedpdf/embedpdf-snippet-1.5.0.tgz", "heic2any": "^0.0.4", + "highlight.js": "^11.11.1", "html2canvas": "^1.4.1", "i18next": "^25.7.2", "i18next-browser-languagedetector": "^8.2.0", "i18next-http-backend": "^3.0.2", - "jspdf": "^3.0.3", + "jspdf": "^4.0.0", + "jspdf-autotable": "^5.0.2", "jszip": "^3.10.1", "lucide": "^0.546.0", + "markdown-it": "^14.1.0", + "markdown-it-abbr": "^2.0.0", + "markdown-it-anchor": "^9.2.0", + "markdown-it-deflist": "^3.0.0", + "markdown-it-emoji": "^3.0.0", + "markdown-it-footnote": "^4.0.0", + "markdown-it-ins": "^4.0.0", + "markdown-it-mark": "^4.0.0", + "markdown-it-sub": "^2.0.0", + "markdown-it-sup": "^2.0.0", + "markdown-it-task-lists": "^2.1.1", + "markdown-it-toc-done-right": "^4.2.0", + "mermaid": "^11.12.2", + "node-forge": "^1.3.3", + "papaparse": "^5.5.3", "pdf-lib": "^1.17.1", "pdfjs-dist": "^5.4.296", "pdfkit": "^0.17.2", + "postal-mime": "^2.7.1", "sortablejs": "^1.15.6", "tailwindcss": "^4.1.14", "terser": "^5.44.0", "tesseract.js": "^6.0.1", "tiff": "^7.1.2", - "utif": "^3.1.0" + "utif": "^3.1.0", + "vite-plugin-static-copy": "^3.1.4", + "xlsx": "file:vendor/sheetjs/xlsx-0.20.2.tgz", + "zgapdfsigner": "^2.7.5" }, "devDependencies": { + "@eslint/js": "^9.39.2", "@testing-library/dom": "^10.4.1", "@types/blob-stream": "^0.1.33", "@types/html2canvas": "^1.0.0", @@ -50,12 +80,288 @@ "@types/utif": "^3.0.6", "@vitest/coverage-v8": "^3.2.4", "@vitest/ui": "^3.2.4", + "eslint": "^9.39.2", + "eslint-config-prettier": "^10.1.8", + "globals": "^17.0.0", + "husky": "^9.1.7", "jsdom": "^27.0.1", + "lint-staged": "^16.2.7", "prettier": "^3.6.2", "typescript": "~5.9.3", + "typescript-eslint": "^8.51.0", "vite": "^7.1.11", + "vite-plugin-compression": "^0.5.1", + "vite-plugin-handlebars": "^2.0.0", "vite-plugin-node-polyfills": "^0.24.0", - "vitest": "^3.2.4" + "vitepress": "^1.6.4", + "vitest": "^3.2.4", + "vue": "^3.5.26" + } + }, + "node_modules/@acemir/cssom": { + "version": "0.9.30", + "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.30.tgz", + "integrity": "sha512-9CnlMCI0LmCIq0olalQqdWrJHPzm0/tw3gzOA9zJSgvFX7Xau3D24mAGa4BtwxwY69nsuJW6kQqqCzf/mEcQgg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@algolia/abtesting": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.12.2.tgz", + "integrity": "sha512-oWknd6wpfNrmRcH0vzed3UPX0i17o4kYLM5OMITyMVM2xLgaRbIafoxL0e8mcrNNb0iORCJA0evnNDKRYth5WQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz", + "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", + "@algolia/autocomplete-shared": "1.17.7" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz", + "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz", + "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz", + "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/client-abtesting": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.46.2.tgz", + "integrity": "sha512-oRSUHbylGIuxrlzdPA8FPJuwrLLRavOhAmFGgdAvMcX47XsyM+IOGa9tc7/K5SPvBqn4nhppOCEz7BrzOPWc4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.46.2.tgz", + "integrity": "sha512-EPBN2Oruw0maWOF4OgGPfioTvd+gmiNwx0HmD9IgmlS+l75DatcBkKOPNJN+0z3wBQWUO5oq602ATxIfmTQ8bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", + "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.46.2.tgz", + "integrity": "sha512-6dBZko2jt8FmQcHCbmNLB0kCV079Mx/DJcySTL3wirgDBUH7xhY1pOuUTLMiGkqM5D8moVZTvTdRKZUJRkrwBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.46.2.tgz", + "integrity": "sha512-1waE2Uqh/PHNeDXGn/PM/WrmYOBiUGSVxAWqiJIj73jqPqvfzZgzdakHscIVaDl6Cp+j5dwjsZ5LCgaUr6DtmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.46.2.tgz", + "integrity": "sha512-EgOzTZkyDcNL6DV0V/24+oBJ+hKo0wNgyrOX/mePBM9bc9huHxIY2352sXmoZ648JXXY2x//V1kropF/Spx83w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.46.2.tgz", + "integrity": "sha512-ZsOJqu4HOG5BlvIFnMU0YKjQ9ZI6r3C31dg2jk5kMWPSdhJpYL9xa5hEe7aieE+707dXeMI4ej3diy6mXdZpgA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion": { + "version": "1.46.2", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.46.2.tgz", + "integrity": "sha512-1Uw2OslTWiOFDtt83y0bGiErJYy5MizadV0nHnOoHFWMoDqWW0kQoMFI65pXqRSkVvit5zjXSLik2xMiyQJDWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring": { + "version": "1.46.2", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.46.2.tgz", + "integrity": "sha512-xk9f+DPtNcddWN6E7n1hyNNsATBCHIqAvVGG2EAGHJc4AFYL18uM/kMTiOKXE/LKDPyy1JhIerrh9oYb7RBrgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.46.2.tgz", + "integrity": "sha512-NApbTPj9LxGzNw4dYnZmj2BoXiAc8NmbbH6qBNzQgXklGklt/xldTvu+FACN6ltFsTzoNU6j2mWNlHQTKGC5+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", + "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", + "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", + "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" } }, "node_modules/@ampproject/remapping": { @@ -72,10 +378,23 @@ "node": ">=6.0.0" } }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "license": "MIT", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@asamuzakjp/css-color": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.0.5.tgz", - "integrity": "sha512-lMrXidNhPGsDjytDy11Vwlb6OIGrT3CmLg3VWNFyWkLWtijKl7xjvForlh8vuj0SHGjgl4qZEQzUmYTeQA2JFQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.1.tgz", + "integrity": "sha512-B0Hv6G3gWGMn0xKJ0txEi/jM5iFpT3MfDxmhZFb4W047GvytCf1DHQ1D69W3zHI4yWe2aTZAA0JnbMZ7Xc8DuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -83,23 +402,13 @@ "@csstools/css-color-parser": "^3.1.0", "@csstools/css-parser-algorithms": "^3.0.5", "@csstools/css-tokenizer": "^3.0.4", - "lru-cache": "^11.2.1" - } - }, - "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", - "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "20 || >=22" + "lru-cache": "^11.2.4" } }, "node_modules/@asamuzakjp/dom-selector": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.2.tgz", - "integrity": "sha512-ccKogJI+0aiDhOahdjANIc9SDixSud1gbwdVrhn7kMopAtLXqsz9MKmQQtIl6Y5aC2IYq+j4dz/oedL2AVMmVQ==", + "version": "6.7.6", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.6.tgz", + "integrity": "sha512-hBaJER6A9MpdG3WgdlOolHmbOYvSk46y7IQN/1+iqiCuUu6iWdQrs9DGKF8ocqsEqWujWf/V7b7vaDgiUmIvUg==", "dev": true, "license": "MIT", "dependencies": { @@ -107,17 +416,7 @@ "bidi-js": "^1.0.3", "css-tree": "^3.1.0", "is-potential-custom-element-name": "^1.0.1", - "lru-cache": "^11.2.2" - } - }, - "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", - "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "20 || >=22" + "lru-cache": "^11.2.4" } }, "node_modules/@asamuzakjp/nwsapi": { @@ -175,1366 +474,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", - "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz", - "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-flow": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.27.1.tgz", - "integrity": "sha512-p9OkPbZ5G7UT1MofwYFigGebnrzGJacoBSQM0/6bi/PUMVE+qlWDD/OalvQKbwgQzU6dl0xAv6r4X7Jme0RYxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", - "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", - "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.28.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", - "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-remap-async-to-generator": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.4.tgz", - "integrity": "sha512-1yxmvN0MJHOhPVmAsmoW5liWwoILobu/d/ShymZmj867bAdxGbehIrew1DuLpw2Ukv+qDSSPQdYW1dLNE7t11A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", - "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", - "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.3", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", - "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", - "@babel/traverse": "^7.28.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", - "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/template": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz", - "integrity": "sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", - "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", - "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.28.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", - "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.27.1.tgz", - "integrity": "sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-flow": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", - "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz", - "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", - "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz", - "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", - "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", - "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz", - "integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.28.0", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", - "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", - "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", - "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", - "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz", - "integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", - "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", - "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", - "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", - "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", - "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.3.tgz", - "integrity": "sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.0", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.27.1", - "@babel/plugin-syntax-import-attributes": "^7.27.1", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.28.0", - "@babel/plugin-transform-async-to-generator": "^7.27.1", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.0", - "@babel/plugin-transform-class-properties": "^7.27.1", - "@babel/plugin-transform-class-static-block": "^7.28.3", - "@babel/plugin-transform-classes": "^7.28.3", - "@babel/plugin-transform-computed-properties": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.28.0", - "@babel/plugin-transform-dotall-regex": "^7.27.1", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.0", - "@babel/plugin-transform-exponentiation-operator": "^7.27.1", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.27.1", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-modules-systemjs": "^7.27.1", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", - "@babel/plugin-transform-numeric-separator": "^7.27.1", - "@babel/plugin-transform-object-rest-spread": "^7.28.0", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.27.1", - "@babel/plugin-transform-private-property-in-object": "^7.27.1", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.3", - "@babel/plugin-transform-regexp-modifiers": "^7.27.1", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.27.1", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.27.1", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.14", - "babel-plugin-polyfill-corejs3": "^0.13.0", - "babel-plugin-polyfill-regenerator": "^0.6.5", - "core-js-compat": "^3.43.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-flow": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.27.1.tgz", - "integrity": "sha512-ez3a2it5Fn6P54W8QkbfIyyIbxlXvcxyWHHvno1Wg0Ej5eiJY5hBb8ExttoIOJJk7V2dZE6prP7iby5q2aQ0Lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-transform-flow-strip-types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz", - "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-typescript": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/register": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.28.3.tgz", - "integrity": "sha512-CieDOtd8u208eI49bYl4z1J22ySFw87IGwE+IswFEExH7e3rLgKb0WNQeumnacQ1+VoDJLYI5QFA3AJZuyZQfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "find-cache-dir": "^2.0.0", - "make-dir": "^2.1.0", - "pirates": "^4.0.6", - "source-map-support": "^0.5.16" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/runtime": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", @@ -1544,40 +483,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", - "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/types": { "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", @@ -1601,6 +506,82 @@ "node": ">=18" } }, + "node_modules/@bentopdf/gs-wasm": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@bentopdf/gs-wasm/-/gs-wasm-0.1.0.tgz", + "integrity": "sha512-C71zxZW4R7Oa6fdya5leTh2VOZOxqH8IQlveh13OeuwZ2ulrovSi9629xTzAiIeeVKvDZma1Klxy4MuK65xe9w==", + "license": "AGPL-3.0", + "peer": true, + "dependencies": { + "@types/emscripten": "^1.39.10" + } + }, + "node_modules/@bentopdf/pymupdf-wasm": { + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/@bentopdf/pymupdf-wasm/-/pymupdf-wasm-0.11.12.tgz", + "integrity": "sha512-AcSg7v7pVhYcH23qLDEj3yTABlGIkZULPmrvWHRtEyD5QMS0TWOLUq/c0ATO371PKVlI4jEUpCBUj+iBsFJwVQ==", + "license": "AGPL-3.0", + "peerDependencies": { + "@bentopdf/gs-wasm": "*" + } + }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz", + "integrity": "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==", + "license": "MIT" + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/cst-dts-gen/node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast/node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "license": "Apache-2.0" + }, "node_modules/@csstools/color-helpers": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", @@ -1698,9 +679,9 @@ } }, "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.14.tgz", - "integrity": "sha512-zSlIxa20WvMojjpCSy8WrNpcZ61RqfTfX3XTaOeVlGJrt/8HF3YbzgFZa01yTbT4GWQLwfTcC3EB8i3XnB647Q==", + "version": "1.0.22", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.22.tgz", + "integrity": "sha512-qBcx6zYlhleiFfdtzkRgwNC7VVoAwfK76Vmsw5t+PbvtdknO9StgRk7ROvq9so1iqbdW4uLIDAsXRsTfUrIoOw==", "dev": true, "funding": [ { @@ -1715,9 +696,6 @@ "license": "MIT-0", "engines": { "node": ">=18" - }, - "peerDependencies": { - "postcss": "^8.4" } }, "node_modules/@csstools/css-tokenizer": { @@ -1741,11 +719,63 @@ "node": ">=18" } }, + "node_modules/@docsearch/css": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.2.tgz", + "integrity": "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@docsearch/js": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.8.2.tgz", + "integrity": "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/react": "3.8.2", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/react": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.2.tgz", + "integrity": "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.17.7", + "@algolia/autocomplete-preset-algolia": "1.17.7", + "@docsearch/css": "3.8.2", + "algoliasearch": "^5.14.2" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, "node_modules/@embedpdf/core": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@embedpdf/core/-/core-1.5.0.tgz", "integrity": "sha512-Yrh9XoVaT8cUgzgqpJ7hx5wg6BqQrCFirqqlSwVb+Ly9oNn4fZbR9GycIWmzJOU5XBnaOJjXfQSaDyoNP0woNA==", "license": "MIT", + "peer": true, "dependencies": { "@embedpdf/engines": "1.5.0", "@embedpdf/models": "1.5.0" @@ -1896,6 +926,7 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-history/-/plugin-history-1.5.0.tgz", "integrity": "sha512-p7PTNNaIr4gH3jLwX+eLJe1DeUXgi21kVGN6SRx/pocH8esg4jqoOeD/YiRRZoZnPOiy0jBXVhkPkwSmY7a2hQ==", "license": "MIT", + "peer": true, "dependencies": { "@embedpdf/models": "1.5.0" }, @@ -1912,6 +943,7 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-interaction-manager/-/plugin-interaction-manager-1.5.0.tgz", "integrity": "sha512-ckHgTfvkW6c5Ta7Mc+Dl9C2foVnvEpqEJ84wyBnqrU0OWbe/jsiPhyKBVeartMGqNI/kVfaQTXupyrKhekAVmg==", "license": "MIT", + "peer": true, "dependencies": { "@embedpdf/models": "1.5.0" }, @@ -1929,6 +961,7 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-loader/-/plugin-loader-1.5.0.tgz", "integrity": "sha512-P4YpIZfaW69etYIjphyaL4cGl2pB14h3OdTE0tRQ2pZYZHFLTvlt4q9B3PVSdhlSrHK5nob7jfLGon2U7xCslg==", "license": "MIT", + "peer": true, "dependencies": { "@embedpdf/models": "1.5.0" }, @@ -2001,6 +1034,7 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-render/-/plugin-render-1.5.0.tgz", "integrity": "sha512-ywwSj0ByrlkvrJIHKRzqxARkOZriki8VJUC+T4MV8fGyF4CzvCRJyKlPktahFz+VxhoodqTh7lBCib68dH+GvA==", "license": "MIT", + "peer": true, "dependencies": { "@embedpdf/models": "1.5.0" }, @@ -2035,6 +1069,7 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-scroll/-/plugin-scroll-1.5.0.tgz", "integrity": "sha512-RNmTZCZ8X1mA8cw9M7TMDuhO9GtkOalGha2bBL3En3D1IlDRS7PzNNMSMV7eqT7OQICSTltlpJ8p8Qi5esvL/Q==", "license": "MIT", + "peer": true, "dependencies": { "@embedpdf/models": "1.5.0" }, @@ -2071,6 +1106,7 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-selection/-/plugin-selection-1.5.0.tgz", "integrity": "sha512-zrxLBAZQoPswDuf9q9DrYaQc6B0Ysc2U1hueTjNH/4+ydfl0BFXZkKR63C2e3YmWtXvKjkoIj0GyPzsiBORLUw==", "license": "MIT", + "peer": true, "dependencies": { "@embedpdf/models": "1.5.0" }, @@ -2161,6 +1197,7 @@ "resolved": "https://registry.npmjs.org/@embedpdf/plugin-viewport/-/plugin-viewport-1.5.0.tgz", "integrity": "sha512-G8GDyYRhfehw72+r4qKkydnA5+AU8qH67g01Y12b0DzI0VIzymh/05Z4dK8DsY3jyWPXJfw2hlg5+KDHaMBHgQ==", "license": "MIT", + "peer": true, "dependencies": { "@embedpdf/models": "1.5.0" }, @@ -2207,9 +1244,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", - "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", "cpu": [ "ppc64" ], @@ -2223,9 +1260,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", - "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", "cpu": [ "arm" ], @@ -2239,9 +1276,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", - "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", "cpu": [ "arm64" ], @@ -2255,9 +1292,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", - "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", "cpu": [ "x64" ], @@ -2271,9 +1308,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", - "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", "cpu": [ "arm64" ], @@ -2287,9 +1324,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", - "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", "cpu": [ "x64" ], @@ -2303,9 +1340,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", - "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", "cpu": [ "arm64" ], @@ -2319,9 +1356,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", - "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", "cpu": [ "x64" ], @@ -2335,9 +1372,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", - "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", "cpu": [ "arm" ], @@ -2351,9 +1388,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", - "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", "cpu": [ "arm64" ], @@ -2367,9 +1404,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", - "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", "cpu": [ "ia32" ], @@ -2383,9 +1420,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", - "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", "cpu": [ "loong64" ], @@ -2399,9 +1436,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", - "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", "cpu": [ "mips64el" ], @@ -2415,9 +1452,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", - "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", "cpu": [ "ppc64" ], @@ -2431,9 +1468,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", - "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", "cpu": [ "riscv64" ], @@ -2447,9 +1484,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", - "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", "cpu": [ "s390x" ], @@ -2463,9 +1500,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", - "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", "cpu": [ "x64" ], @@ -2479,9 +1516,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", - "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", "cpu": [ "arm64" ], @@ -2495,9 +1532,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", - "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", "cpu": [ "x64" ], @@ -2511,9 +1548,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", - "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", "cpu": [ "arm64" ], @@ -2527,9 +1564,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", - "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", "cpu": [ "x64" ], @@ -2543,9 +1580,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", - "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", "cpu": [ "arm64" ], @@ -2559,9 +1596,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", - "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", "cpu": [ "x64" ], @@ -2575,9 +1612,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", - "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", "cpu": [ "arm64" ], @@ -2591,9 +1628,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", - "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", "cpu": [ "ia32" ], @@ -2607,9 +1644,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", - "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", "cpu": [ "x64" ], @@ -2622,6 +1659,181 @@ "node": ">=18" } }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "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_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==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "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==", + "dev": true, + "license": "MIT", + "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, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "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==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "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==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "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.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "dev": true, + "license": "MIT", + "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", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "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==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@exodus/bytes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.8.0.tgz", + "integrity": "sha512-8JPn18Bcp8Uo1T82gR8lh2guEOa5KKU/IEKvvdp0sgmi7coPBWf1Doi1EXsGZb2ehc8ym/StJCjffYV+ne7sXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@exodus/crypto": "^1.0.0-rc.4" + }, + "peerDependenciesMeta": { + "@exodus/crypto": { + "optional": true + } + } + }, "node_modules/@fontsource/cedarville-cursive": { "version": "5.2.7", "resolved": "https://registry.npmjs.org/@fontsource/cedarville-cursive/-/cedarville-cursive-5.2.7.tgz", @@ -2685,6 +1897,85 @@ "url": "https://github.com/sponsors/ayuhito" } }, + "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, + "license": "Apache-2.0", + "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, + "license": "Apache-2.0", + "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, + "license": "Apache-2.0", + "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, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@iconify-json/simple-icons": { + "version": "1.2.65", + "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.65.tgz", + "integrity": "sha512-v/O0UeqrDz6ASuRVE5g2Puo5aWyej4M/CxX6WYDBARgswwxK0mp3VQbGgPFEAAUU9QN02IjTgjMuO021gpWf2w==", + "dev": true, + "license": "CC0-1.0", + "dependencies": { + "@iconify/types": "*" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz", + "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==", + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^1.1.0", + "@iconify/types": "^2.0.0", + "mlly": "^1.8.0" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -2702,85 +1993,6 @@ "node": ">=12" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -2846,10 +2058,58 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@kenjiuno/decompressrtf": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@kenjiuno/decompressrtf/-/decompressrtf-0.1.4.tgz", + "integrity": "sha512-v9c/iFz17jRWyd2cRnrvJg4VOg/4I/VCk+bG8JnoX2gJ9sAesPzo3uTqcmlVXdpasTI8hChpBVw00pghKe3qTQ==", + "license": "BSD-2-Clause" + }, + "node_modules/@kenjiuno/msgreader": { + "version": "1.27.1-alpha.1", + "resolved": "https://registry.npmjs.org/@kenjiuno/msgreader/-/msgreader-1.27.1-alpha.1.tgz", + "integrity": "sha512-r/Fc6cW+68YpYfA8K0uRI31AV484QzcFzJWZkVz5HHBUf1TrzznvSZ9rRwCRqdO2uTLoMtMf7FovZ+MNfa379g==", + "license": "Apache-2.0", + "dependencies": { + "@kenjiuno/decompressrtf": "^0.1.3", + "iconv-lite": "^0.6.3" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@matbee/libreoffice-converter": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@matbee/libreoffice-converter/-/libreoffice-converter-2.3.1.tgz", + "integrity": "sha512-Nyom9JRxzO6N5rEAIqvxF03k4H2CbQqB+5CtSNBtgSXXJCj3oZYZ7DXgapFyWWbI08nZ3gMdo88uxNrbxMOkyA==", + "license": "MPL-2.0", + "dependencies": { + "zod": "^4.1.13" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "sharp": ">=0.32.0" + }, + "peerDependenciesMeta": { + "sharp": { + "optional": true + } + } + }, + "node_modules/@mermaid-js/parser": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.3.tgz", + "integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==", + "license": "MIT", + "dependencies": { + "langium": "3.3.1" + } + }, "node_modules/@napi-rs/canvas": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.80.tgz", - "integrity": "sha512-DxuT1ClnIPts1kQx8FBmkk4BQDTfI5kIzywAaMjQSXfNnra5UFU9PwurXrl+Je3bJ6BGsp/zmshVVFbCmyI+ww==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.88.tgz", + "integrity": "sha512-/p08f93LEbsL5mDZFQ3DBxcPv/I4QG9EDYRRq1WNlCOXVfAHBTHMSVMwxlqG/AtnSfUr9+vgfN7MKiyDo0+Weg==", "license": "MIT", "optional": true, "workspaces": [ @@ -2858,23 +2118,28 @@ "engines": { "node": ">= 10" }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, "optionalDependencies": { - "@napi-rs/canvas-android-arm64": "0.1.80", - "@napi-rs/canvas-darwin-arm64": "0.1.80", - "@napi-rs/canvas-darwin-x64": "0.1.80", - "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.80", - "@napi-rs/canvas-linux-arm64-gnu": "0.1.80", - "@napi-rs/canvas-linux-arm64-musl": "0.1.80", - "@napi-rs/canvas-linux-riscv64-gnu": "0.1.80", - "@napi-rs/canvas-linux-x64-gnu": "0.1.80", - "@napi-rs/canvas-linux-x64-musl": "0.1.80", - "@napi-rs/canvas-win32-x64-msvc": "0.1.80" + "@napi-rs/canvas-android-arm64": "0.1.88", + "@napi-rs/canvas-darwin-arm64": "0.1.88", + "@napi-rs/canvas-darwin-x64": "0.1.88", + "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.88", + "@napi-rs/canvas-linux-arm64-gnu": "0.1.88", + "@napi-rs/canvas-linux-arm64-musl": "0.1.88", + "@napi-rs/canvas-linux-riscv64-gnu": "0.1.88", + "@napi-rs/canvas-linux-x64-gnu": "0.1.88", + "@napi-rs/canvas-linux-x64-musl": "0.1.88", + "@napi-rs/canvas-win32-arm64-msvc": "0.1.88", + "@napi-rs/canvas-win32-x64-msvc": "0.1.88" } }, "node_modules/@napi-rs/canvas-android-arm64": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.80.tgz", - "integrity": "sha512-sk7xhN/MoXeuExlggf91pNziBxLPVUqF2CAVnB57KLG/pz7+U5TKG8eXdc3pm0d7Od0WreB6ZKLj37sX9muGOQ==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.88.tgz", + "integrity": "sha512-KEaClPnZuVxJ8smUWjV1wWFkByBO/D+vy4lN+Dm5DFH514oqwukxKGeck9xcKJhaWJGjfruGmYGiwRe//+/zQQ==", "cpu": [ "arm64" ], @@ -2885,12 +2150,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-darwin-arm64": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.80.tgz", - "integrity": "sha512-O64APRTXRUiAz0P8gErkfEr3lipLJgM6pjATwavZ22ebhjYl/SUbpgM0xcWPQBNMP1n29afAC/Us5PX1vg+JNQ==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.88.tgz", + "integrity": "sha512-Xgywz0dDxOKSgx3eZnK85WgGMmGrQEW7ZLA/E7raZdlEE+xXCozobgqz2ZvYigpB6DJFYkqnwHjqCOTSDGlFdg==", "cpu": [ "arm64" ], @@ -2901,12 +2170,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-darwin-x64": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.80.tgz", - "integrity": "sha512-FqqSU7qFce0Cp3pwnTjVkKjjOtxMqRe6lmINxpIZYaZNnVI0H5FtsaraZJ36SiTHNjZlUB69/HhxNDT1Aaa9vA==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.88.tgz", + "integrity": "sha512-Yz4wSCIQOUgNucgk+8NFtQxQxZV5NO8VKRl9ePKE6XoNyNVC8JDqtvhh3b3TPqKK8W5p2EQpAr1rjjm0mfBxdg==", "cpu": [ "x64" ], @@ -2917,12 +2190,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.80.tgz", - "integrity": "sha512-eyWz0ddBDQc7/JbAtY4OtZ5SpK8tR4JsCYEZjCE3dI8pqoWUC8oMwYSBGCYfsx2w47cQgQCgMVRVTFiiO38hHQ==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.88.tgz", + "integrity": "sha512-9gQM2SlTo76hYhxHi2XxWTAqpTOb+JtxMPEIr+H5nAhHhyEtNmTSDRtz93SP7mGd2G3Ojf2oF5tP9OdgtgXyKg==", "cpu": [ "arm" ], @@ -2933,12 +2210,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-linux-arm64-gnu": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.80.tgz", - "integrity": "sha512-qwA63t8A86bnxhuA/GwOkK3jvb+XTQaTiVML0vAWoHyoZYTjNs7BzoOONDgTnNtr8/yHrq64XXzUoLqDzU+Uuw==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.88.tgz", + "integrity": "sha512-7qgaOBMXuVRk9Fzztzr3BchQKXDxGbY+nwsovD3I/Sx81e+sX0ReEDYHTItNb0Je4NHbAl7D0MKyd4SvUc04sg==", "cpu": [ "arm64" ], @@ -2949,12 +2230,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-linux-arm64-musl": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.80.tgz", - "integrity": "sha512-1XbCOz/ymhj24lFaIXtWnwv/6eFHXDrjP0jYkc6iHQ9q8oXKzUX1Lc6bu+wuGiLhGh2GS/2JlfORC5ZcXimRcg==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.88.tgz", + "integrity": "sha512-kYyNrUsHLkoGHBc77u4Unh067GrfiCUMbGHC2+OTxbeWfZkPt2o32UOQkhnSswKd9Fko/wSqqGkY956bIUzruA==", "cpu": [ "arm64" ], @@ -2965,12 +2250,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.80.tgz", - "integrity": "sha512-XTzR125w5ZMs0lJcxRlS1K3P5RaZ9RmUsPtd1uGt+EfDyYMu4c6SEROYsxyatbbu/2+lPe7MPHOO/0a0x7L/gw==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.88.tgz", + "integrity": "sha512-HVuH7QgzB0yavYdNZDRyAsn/ejoXB0hn8twwFnOqUbCCdkV+REna7RXjSR7+PdfW0qMQ2YYWsLvVBT5iL/mGpw==", "cpu": [ "riscv64" ], @@ -2981,12 +2270,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-linux-x64-gnu": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.80.tgz", - "integrity": "sha512-BeXAmhKg1kX3UCrJsYbdQd3hIMDH/K6HnP/pG2LuITaXhXBiNdh//TVVVVCBbJzVQaV5gK/4ZOCMrQW9mvuTqA==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.88.tgz", + "integrity": "sha512-hvcvKIcPEQrvvJtJnwD35B3qk6umFJ8dFIr8bSymfrSMem0EQsfn1ztys8ETIFndTwdNWJKWluvxztA41ivsEw==", "cpu": [ "x64" ], @@ -2997,12 +2290,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-linux-x64-musl": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.80.tgz", - "integrity": "sha512-x0XvZWdHbkgdgucJsRxprX/4o4sEed7qo9rCQA9ugiS9qE2QvP0RIiEugtZhfLH3cyI+jIRFJHV4Fuz+1BHHMg==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.88.tgz", + "integrity": "sha512-eSMpGYY2xnZSQ6UxYJ6plDboxq4KeJ4zT5HaVkUnbObNN6DlbJe0Mclh3wifAmquXfrlgTZt6zhHsUgz++AK6g==", "cpu": [ "x64" ], @@ -3013,12 +2310,36 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-win32-arm64-msvc": { + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-0.1.88.tgz", + "integrity": "sha512-qcIFfEgHrchyYqRrxsCeTQgpJZ/GqHiqPcU/Fvw/ARVlQeDX1VyFH+X+0gCR2tca6UJrq96vnW+5o7buCq+erA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-win32-x64-msvc": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.80.tgz", - "integrity": "sha512-Z8jPsM6df5V8B1HrCHB05+bDiCxjE9QA//3YrkKIdVDEwn5RKaqOxCJDRJkl48cJbylcrJbW4HxZbTte8juuPg==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.88.tgz", + "integrity": "sha512-ROVqbfS4QyZxYkqmaIBBpbz/BQvAR+05FXM5PAtTYVc0uyY8Y4BHJSMdGAaMf6TdIVRsQsiq+FG/dH9XhvWCFQ==", "cpu": [ "x64" ], @@ -3029,6 +2350,10 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@neslinesli93/qpdf-wasm": { @@ -3064,6 +2389,12 @@ "pako": "^1.0.10" } }, + "node_modules/@phosphor-icons/web": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@phosphor-icons/web/-/web-2.1.2.tgz", + "integrity": "sha512-rPAR9o/bEcp4Cw4DEeZHXf+nlGCMNGkNDRizYHM47NLxz9vvEHp/Tt6FMK1NcWadzw/pFDPnRBGi/ofRya958A==", + "license": "MIT" + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -3104,6 +2435,13 @@ } } }, + "node_modules/@rollup/plugin-inject/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/pluginutils": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", @@ -3127,10 +2465,30 @@ } } }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz", - "integrity": "sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", + "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", "cpu": [ "arm" ], @@ -3141,9 +2499,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.4.tgz", - "integrity": "sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", + "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", "cpu": [ "arm64" ], @@ -3154,9 +2512,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.4.tgz", - "integrity": "sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", + "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", "cpu": [ "arm64" ], @@ -3167,9 +2525,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.4.tgz", - "integrity": "sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", + "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", "cpu": [ "x64" ], @@ -3180,9 +2538,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.4.tgz", - "integrity": "sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", + "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", "cpu": [ "arm64" ], @@ -3193,9 +2551,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.4.tgz", - "integrity": "sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", + "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", "cpu": [ "x64" ], @@ -3206,9 +2564,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.4.tgz", - "integrity": "sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", + "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", "cpu": [ "arm" ], @@ -3219,9 +2577,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.4.tgz", - "integrity": "sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", + "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", "cpu": [ "arm" ], @@ -3232,9 +2590,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.4.tgz", - "integrity": "sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", + "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", "cpu": [ "arm64" ], @@ -3245,9 +2603,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.4.tgz", - "integrity": "sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", + "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", "cpu": [ "arm64" ], @@ -3258,9 +2616,22 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.4.tgz", - "integrity": "sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", + "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", + "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", "cpu": [ "loong64" ], @@ -3271,9 +2642,22 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.4.tgz", - "integrity": "sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", + "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", + "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", "cpu": [ "ppc64" ], @@ -3284,9 +2668,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.4.tgz", - "integrity": "sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", + "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", "cpu": [ "riscv64" ], @@ -3297,9 +2681,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.4.tgz", - "integrity": "sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", + "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", "cpu": [ "riscv64" ], @@ -3310,9 +2694,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.4.tgz", - "integrity": "sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", + "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", "cpu": [ "s390x" ], @@ -3323,9 +2707,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.4.tgz", - "integrity": "sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", + "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", "cpu": [ "x64" ], @@ -3336,9 +2720,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.4.tgz", - "integrity": "sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", + "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", "cpu": [ "x64" ], @@ -3348,10 +2732,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", + "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.4.tgz", - "integrity": "sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", + "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", "cpu": [ "arm64" ], @@ -3362,9 +2759,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.4.tgz", - "integrity": "sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", + "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", "cpu": [ "arm64" ], @@ -3375,9 +2772,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.4.tgz", - "integrity": "sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", + "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", "cpu": [ "ia32" ], @@ -3388,9 +2785,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.4.tgz", - "integrity": "sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", + "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", "cpu": [ "x64" ], @@ -3401,9 +2798,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.4.tgz", - "integrity": "sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", + "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", "cpu": [ "x64" ], @@ -3413,20 +2810,106 @@ "win32" ] }, + "node_modules/@shikijs/core": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz", + "integrity": "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.4" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz", + "integrity": "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^3.1.0" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz", + "integrity": "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-2.5.0.tgz", + "integrity": "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-2.5.0.tgz", + "integrity": "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/transformers": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-2.5.0.tgz", + "integrity": "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/types": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-2.5.0.tgz", + "integrity": "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "dev": true, + "license": "MIT" + }, "node_modules/@sveltejs/acorn-typescript": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.8.tgz", "integrity": "sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA==", "license": "MIT", - "peer": true, "peerDependencies": { "acorn": "^8.9.0" } }, "node_modules/@swc/helpers": { - "version": "0.5.17", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", - "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", + "version": "0.5.18", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.18.tgz", + "integrity": "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.8.0" @@ -3439,47 +2922,47 @@ "license": "0BSD" }, "node_modules/@tailwindcss/node": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.15.tgz", - "integrity": "sha512-HF4+7QxATZWY3Jr8OlZrBSXmwT3Watj0OogeDvdUY/ByXJHQ+LBtqA2brDb3sBxYslIFx6UP94BJ4X6a4L9Bmw==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", + "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", - "jiti": "^2.6.0", + "jiti": "^2.6.1", "lightningcss": "1.30.2", - "magic-string": "^0.30.19", + "magic-string": "^0.30.21", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.15" + "tailwindcss": "4.1.18" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.15.tgz", - "integrity": "sha512-krhX+UOOgnsUuks2SR7hFafXmLQrKxB4YyRTERuCE59JlYL+FawgaAlSkOYmDRJdf1Q+IFNDMl9iRnBW7QBDfQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", + "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", "license": "MIT", "engines": { "node": ">= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.15", - "@tailwindcss/oxide-darwin-arm64": "4.1.15", - "@tailwindcss/oxide-darwin-x64": "4.1.15", - "@tailwindcss/oxide-freebsd-x64": "4.1.15", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.15", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.15", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.15", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.15", - "@tailwindcss/oxide-linux-x64-musl": "4.1.15", - "@tailwindcss/oxide-wasm32-wasi": "4.1.15", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.15", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.15" + "@tailwindcss/oxide-android-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-x64": "4.1.18", + "@tailwindcss/oxide-freebsd-x64": "4.1.18", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-x64-musl": "4.1.18", + "@tailwindcss/oxide-wasm32-wasi": "4.1.18", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.15.tgz", - "integrity": "sha512-TkUkUgAw8At4cBjCeVCRMc/guVLKOU1D+sBPrHt5uVcGhlbVKxrCaCW9OKUIBv1oWkjh4GbunD/u/Mf0ql6kEA==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", + "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", "cpu": [ "arm64" ], @@ -3493,9 +2976,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.15.tgz", - "integrity": "sha512-xt5XEJpn2piMSfvd1UFN6jrWXyaKCwikP4Pidcf+yfHTSzSpYhG3dcMktjNkQO3JiLCp+0bG0HoWGvz97K162w==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", + "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", "cpu": [ "arm64" ], @@ -3509,9 +2992,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.15.tgz", - "integrity": "sha512-TnWaxP6Bx2CojZEXAV2M01Yl13nYPpp0EtGpUrY+LMciKfIXiLL2r/SiSRpagE5Fp2gX+rflp/Os1VJDAyqymg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", + "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", "cpu": [ "x64" ], @@ -3525,9 +3008,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.15.tgz", - "integrity": "sha512-quISQDWqiB6Cqhjc3iWptXVZHNVENsWoI77L1qgGEHNIdLDLFnw3/AfY7DidAiiCIkGX/MjIdB3bbBZR/G2aJg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", + "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", "cpu": [ "x64" ], @@ -3541,9 +3024,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.15.tgz", - "integrity": "sha512-ObG76+vPlab65xzVUQbExmDU9FIeYLQ5k2LrQdR2Ud6hboR+ZobXpDoKEYXf/uOezOfIYmy2Ta3w0ejkTg9yxg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", + "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", "cpu": [ "arm" ], @@ -3557,9 +3040,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.15.tgz", - "integrity": "sha512-4WbBacRmk43pkb8/xts3wnOZMDKsPFyEH/oisCm2q3aLZND25ufvJKcDUpAu0cS+CBOL05dYa8D4U5OWECuH/Q==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", + "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", "cpu": [ "arm64" ], @@ -3573,9 +3056,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.15.tgz", - "integrity": "sha512-AbvmEiteEj1nf42nE8skdHv73NoR+EwXVSgPY6l39X12Ex8pzOwwfi3Kc8GAmjsnsaDEbk+aj9NyL3UeyHcTLg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", + "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", "cpu": [ "arm64" ], @@ -3589,9 +3072,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.15.tgz", - "integrity": "sha512-+rzMVlvVgrXtFiS+ES78yWgKqpThgV19ISKD58Ck+YO5pO5KjyxLt7AWKsWMbY0R9yBDC82w6QVGz837AKQcHg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", + "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", "cpu": [ "x64" ], @@ -3605,9 +3088,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.15.tgz", - "integrity": "sha512-fPdEy7a8eQN9qOIK3Em9D3TO1z41JScJn8yxl/76mp4sAXFDfV4YXxsiptJcOwy6bGR+70ZSwFIZhTXzQeqwQg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", + "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", "cpu": [ "x64" ], @@ -3621,9 +3104,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.15.tgz", - "integrity": "sha512-sJ4yd6iXXdlgIMfIBXuVGp/NvmviEoMVWMOAGxtxhzLPp9LOj5k0pMEMZdjeMCl4C6Up+RM8T3Zgk+BMQ0bGcQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", + "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -3638,10 +3121,10 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.5.0", - "@emnapi/runtime": "^1.5.0", + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.0.7", + "@napi-rs/wasm-runtime": "^1.1.0", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, @@ -3650,7 +3133,7 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.5.0", + "version": "1.7.1", "inBundle": true, "license": "MIT", "optional": true, @@ -3660,7 +3143,7 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.5.0", + "version": "1.7.1", "inBundle": true, "license": "MIT", "optional": true, @@ -3678,13 +3161,13 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { - "version": "1.0.7", + "version": "1.1.0", "inBundle": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.5.0", - "@emnapi/runtime": "^1.5.0", + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, @@ -3704,9 +3187,9 @@ "optional": true }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.15.tgz", - "integrity": "sha512-sJGE5faXnNQ1iXeqmRin7Ds/ru2fgCiaQZQQz3ZGIDtvbkeV85rAZ0QJFMDg0FrqsffZG96H1U9AQlNBRLsHVg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", + "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", "cpu": [ "arm64" ], @@ -3720,9 +3203,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.15.tgz", - "integrity": "sha512-NLeHE7jUV6HcFKS504bpOohyi01zPXi2PXmjFfkzTph8xRxDdxkRsXm/xDO5uV5K3brrE1cCwbUYmFUSHR3u1w==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", + "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", "cpu": [ "x64" ], @@ -3736,14 +3219,14 @@ } }, "node_modules/@tailwindcss/vite": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.15.tgz", - "integrity": "sha512-B6s60MZRTUil+xKoZoGe6i0Iar5VuW+pmcGlda2FX+guDuQ1G1sjiIy1W0frneVpeL/ZjZ4KEgWZHNrIm++2qA==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.18.tgz", + "integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==", "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.1.15", - "@tailwindcss/oxide": "4.1.15", - "tailwindcss": "4.1.15" + "@tailwindcss/node": "4.1.18", + "@tailwindcss/oxide": "4.1.18", + "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" @@ -3787,13 +3270,267 @@ } }, "node_modules/@types/chai": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", - "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { - "@types/deep-eql": "*" + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "license": "MIT" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", + "license": "MIT" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "license": "MIT", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "license": "MIT" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "license": "MIT" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "license": "MIT" + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", + "license": "MIT" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" } }, "node_modules/@types/deep-eql": { @@ -3803,12 +3540,34 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/emscripten": { + "version": "1.41.5", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.41.5.tgz", + "integrity": "sha512-cMQm7pxu6BxtHyqJ7mQZ2kXWV5SLmugybFdHCBbJ5eHzOo6VhBckEgAT3//rP5FwPHNPeEiq4SmQ5ucBwsOo4Q==", + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/html2canvas": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/html2canvas/-/html2canvas-1.0.0.tgz", @@ -3820,14 +3579,62 @@ "html2canvas": "*" } }, - "node_modules/@types/node": { - "version": "24.7.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.7.0.tgz", - "integrity": "sha512-IbKooQVqUBrlzWTi79E8Fw78l8k1RNtlDDNWsFZs7XonuQSJ8oNYfEeclhprUldXISRMLzBpILuKgPlIxm+/Yw==", - "devOptional": true, + "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, + "license": "MIT" + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.14.0" + "@types/unist": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz", + "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", + "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" } }, "node_modules/@types/pako": { @@ -3836,10 +3643,19 @@ "integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==", "license": "MIT" }, + "node_modules/@types/papaparse": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.5.2.tgz", + "integrity": "sha512-gFnFp/JMzLHCwRf7tQHrNnfhN4eYBVYYI897CGX4MY1tzY9l2aLkVyx2IlKZ/SAqDbB3I1AOZW5gTMGGsqWliA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/pdfkit": { - "version": "0.17.3", - "resolved": "https://registry.npmjs.org/@types/pdfkit/-/pdfkit-0.17.3.tgz", - "integrity": "sha512-E4tp2qFaghqfS4K5TR4Gn1uTIkg0UAkhUgvVIszr5cS6ZmbioPWEkvhNDy3GtR9qdKC8DLQAnaaMlTcf346VsA==", + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/pdfkit/-/pdfkit-0.17.4.tgz", + "integrity": "sha512-odAmVuuguRxKh1X4pbMrJMp8ecwNqHRw6lweupvzK+wuyNmi6wzlUlGVZ9EqMvp3Bs2+L9Ty0sRlrvKL+gsQZg==", "dev": true, "license": "MIT", "dependencies": { @@ -3854,9 +3670,9 @@ "optional": true }, "node_modules/@types/sortablejs": { - "version": "1.15.8", - "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.8.tgz", - "integrity": "sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.9.tgz", + "integrity": "sha512-7HP+rZGE2p886PKV9c9OJzLBI6BBJu1O7lJGYnPyG3fS4/duUCcngkNCjsLwIMV+WMqANe3tt4irrXHSIe68OQ==", "dev": true, "license": "MIT" }, @@ -3867,6 +3683,13 @@ "license": "MIT", "optional": true }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/utif": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@types/utif/-/utif-3.0.6.tgz", @@ -3877,6 +3700,277 @@ "@types/node": "*" } }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.51.0.tgz", + "integrity": "sha512-XtssGWJvypyM2ytBnSnKtHYOGT+4ZwTnBVl36TA4nRO2f4PRNGz5/1OszHzcZCvcBMh+qb7I06uoCmLTRdR9og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.51.0", + "@typescript-eslint/type-utils": "8.51.0", + "@typescript-eslint/utils": "8.51.0", + "@typescript-eslint/visitor-keys": "8.51.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.51.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.51.0.tgz", + "integrity": "sha512-3xP4XzzDNQOIqBMWogftkwxhg5oMKApqY0BAflmLZiFYHqyhSOxv/cd/zPQLTcCXr4AkaKb25joocY0BD1WC6A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.51.0", + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/typescript-estree": "8.51.0", + "@typescript-eslint/visitor-keys": "8.51.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.51.0.tgz", + "integrity": "sha512-Luv/GafO07Z7HpiI7qeEW5NW8HUtZI/fo/kE0YbtQEFpJRUuR0ajcWfCE5bnMvL7QQFrmT/odMe8QZww8X2nfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.51.0", + "@typescript-eslint/types": "^8.51.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.51.0.tgz", + "integrity": "sha512-JhhJDVwsSx4hiOEQPeajGhCWgBMBwVkxC/Pet53EpBVs7zHHtayKefw1jtPaNRXpI9RA2uocdmpdfE7T+NrizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/visitor-keys": "8.51.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.51.0.tgz", + "integrity": "sha512-Qi5bSy/vuHeWyir2C8u/uqGMIlIDu8fuiYWv48ZGlZ/k+PRPHtaAu7erpc7p5bzw2WNNSniuxoMSO4Ar6V9OXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.51.0.tgz", + "integrity": "sha512-0XVtYzxnobc9K0VU7wRWg1yiUrw4oQzexCG2V2IDxxCxhqBMSMbjB+6o91A+Uc0GWtgjCa3Y8bi7hwI0Tu4n5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/typescript-estree": "8.51.0", + "@typescript-eslint/utils": "8.51.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.51.0.tgz", + "integrity": "sha512-TizAvWYFM6sSscmEakjY3sPqGwxZRSywSsPEiuZF6d5GmGD9Gvlsv0f6N8FvAAA0CD06l3rIcWNbsN1e5F/9Ag==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.51.0.tgz", + "integrity": "sha512-1qNjGqFRmlq0VW5iVlcyHBbCjPB7y6SxpBkrbhNWMy/65ZoncXCEPJxkRZL8McrseNH6lFhaxCIaX+vBuFnRng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.51.0", + "@typescript-eslint/tsconfig-utils": "8.51.0", + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/visitor-keys": "8.51.0", + "debug": "^4.3.4", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.51.0.tgz", + "integrity": "sha512-11rZYxSe0zabiKaCP2QAwRf/dnmgFgvTmeDTtZvUvXG3UuAdg/GU02NExmmIXzz3vLGgMdtrIosI84jITQOxUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.51.0", + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/typescript-estree": "8.51.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.51.0.tgz", + "integrity": "sha512-mM/JRQOzhVN1ykejrvwnBRV3+7yTKK8tVANVN3o1O0t0v7o+jqdVu9crPy5Y9dov15TJk/FTIgoUGHrTOVL3Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.51.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, "node_modules/@vitest/coverage-v8": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.4.tgz", @@ -3955,16 +4049,6 @@ } } }, - "node_modules/@vitest/mocker/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, "node_modules/@vitest/pretty-format": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", @@ -4060,25 +4144,23 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.25", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.25.tgz", - "integrity": "sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==", + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.26.tgz", + "integrity": "sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w==", "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.28.5", - "@vue/shared": "3.5.25", - "entities": "^4.5.0", + "@vue/shared": "3.5.26", + "entities": "^7.0.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-core/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.0.tgz", + "integrity": "sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ==", "license": "BSD-2-Clause", - "peer": true, "engines": { "node": ">=0.12" }, @@ -4086,100 +4168,246 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/@vue/compiler-core/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, "node_modules/@vue/compiler-dom": { - "version": "3.5.25", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.25.tgz", - "integrity": "sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==", + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.26.tgz", + "integrity": "sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A==", "license": "MIT", - "peer": true, "dependencies": { - "@vue/compiler-core": "3.5.25", - "@vue/shared": "3.5.25" + "@vue/compiler-core": "3.5.26", + "@vue/shared": "3.5.26" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.25", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.25.tgz", - "integrity": "sha512-PUgKp2rn8fFsI++lF2sO7gwO2d9Yj57Utr5yEsDf3GNaQcowCLKL7sf+LvVFvtJDXUp/03+dC6f2+LCv5aK1ag==", + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.26.tgz", + "integrity": "sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.28.5", - "@vue/compiler-core": "3.5.25", - "@vue/compiler-dom": "3.5.25", - "@vue/compiler-ssr": "3.5.25", - "@vue/shared": "3.5.25", + "@vue/compiler-core": "3.5.26", + "@vue/compiler-dom": "3.5.26", + "@vue/compiler-ssr": "3.5.26", + "@vue/shared": "3.5.26", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, + "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.25", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.25.tgz", - "integrity": "sha512-ritPSKLBcParnsKYi+GNtbdbrIE1mtuFEJ4U1sWeuOMlIziK5GtOL85t5RhsNy4uWIXPgk+OUdpnXiTdzn8o3A==", + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.26.tgz", + "integrity": "sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==", "license": "MIT", - "peer": true, "dependencies": { - "@vue/compiler-dom": "3.5.25", - "@vue/shared": "3.5.25" + "@vue/compiler-dom": "3.5.26", + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" } }, "node_modules/@vue/reactivity": { - "version": "3.5.25", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.25.tgz", - "integrity": "sha512-5xfAypCQepv4Jog1U4zn8cZIcbKKFka3AgWHEFQeK65OW+Ys4XybP6z2kKgws4YB43KGpqp5D/K3go2UPPunLA==", + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.26.tgz", + "integrity": "sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ==", "license": "MIT", - "peer": true, "dependencies": { - "@vue/shared": "3.5.25" + "@vue/shared": "3.5.26" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.25", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.25.tgz", - "integrity": "sha512-Z751v203YWwYzy460bzsYQISDfPjHTl+6Zzwo/a3CsAf+0ccEjQ8c+0CdX1WsumRTHeywvyUFtW6KvNukT/smA==", + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.26.tgz", + "integrity": "sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q==", "license": "MIT", - "peer": true, "dependencies": { - "@vue/reactivity": "3.5.25", - "@vue/shared": "3.5.25" + "@vue/reactivity": "3.5.26", + "@vue/shared": "3.5.26" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.25", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.25.tgz", - "integrity": "sha512-a4WrkYFbb19i9pjkz38zJBg8wa/rboNERq3+hRRb0dHiJh13c+6kAbgqCPfMaJ2gg4weWD3APZswASOfmKwamA==", + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.26.tgz", + "integrity": "sha512-XLLd/+4sPC2ZkN/6+V4O4gjJu6kSDbHAChvsyWgm1oGbdSO3efvGYnm25yCjtFm/K7rrSDvSfPDgN1pHgS4VNQ==", "license": "MIT", - "peer": true, "dependencies": { - "@vue/reactivity": "3.5.25", - "@vue/runtime-core": "3.5.25", - "@vue/shared": "3.5.25", - "csstype": "^3.1.3" + "@vue/reactivity": "3.5.26", + "@vue/runtime-core": "3.5.26", + "@vue/shared": "3.5.26", + "csstype": "^3.2.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.25", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.25.tgz", - "integrity": "sha512-UJaXR54vMG61i8XNIzTSf2Q7MOqZHpp8+x3XLGtE3+fL+nQd+k7O5+X3D/uWrnQXOdMw5VPih+Uremcw+u1woQ==", + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.26.tgz", + "integrity": "sha512-TYKLXmrwWKSodyVuO1WAubucd+1XlLg4set0YoV+Hu8Lo79mp/YMwWV5mC5FgtsDxX3qo1ONrxFaTP1OQgy1uA==", "license": "MIT", - "peer": true, "dependencies": { - "@vue/compiler-ssr": "3.5.25", - "@vue/shared": "3.5.25" + "@vue/compiler-ssr": "3.5.26", + "@vue/shared": "3.5.26" }, "peerDependencies": { - "vue": "3.5.25" + "vue": "3.5.26" } }, "node_modules/@vue/shared": { - "version": "3.5.25", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.25.tgz", - "integrity": "sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==", + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.26.tgz", + "integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==", + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz", + "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==", + "dev": true, "license": "MIT", - "peer": true + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/integrations": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-12.8.2.tgz", + "integrity": "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vueuse/core": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "^4", + "axios": "^1", + "change-case": "^5", + "drauu": "^0.4", + "focus-trap": "^7", + "fuse.js": "^7", + "idb-keyval": "^6", + "jwt-decode": "^4", + "nprogress": "^0.2", + "qrcode": "^1.5", + "sortablejs": "^1", + "universal-cookie": "^7" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz", + "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz", + "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } }, "node_modules/abort-controller": { "version": "3.0.0", @@ -4198,6 +4426,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4205,6 +4434,16 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -4215,6 +4454,66 @@ "node": ">= 14" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "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" + } + }, + "node_modules/algoliasearch": { + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.46.2.tgz", + "integrity": "sha512-qqAXW9QvKf2tTyhpDA4qXv1IfBwD2eduSW6tUEBFIfCeE9gn9HQ9I5+MaKoenRuHrzk5sQoNh1/iof8mY7uD6Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@algolia/abtesting": "1.12.2", + "@algolia/client-abtesting": "5.46.2", + "@algolia/client-analytics": "5.46.2", + "@algolia/client-common": "5.46.2", + "@algolia/client-insights": "5.46.2", + "@algolia/client-personalization": "5.46.2", + "@algolia/client-query-suggestions": "5.46.2", + "@algolia/client-search": "5.46.2", + "@algolia/ingestion": "1.46.2", + "@algolia/monitoring": "1.46.2", + "@algolia/recommend": "5.46.2", + "@algolia/requester-browser-xhr": "5.46.2", + "@algolia/requester-fetch": "5.46.2", + "@algolia/requester-node-http": "5.46.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ansi-escapes": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.2.0.tgz", + "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -4239,6 +4538,19 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/archiver": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", @@ -4275,143 +4587,11 @@ "node": ">= 14" } }, - "node_modules/archiver-utils/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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.2.1" - } - }, - "node_modules/archiver-utils/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/archiver-utils/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", - "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/archiver-utils/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/archiver/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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.2.1" - } - }, - "node_modules/archiver/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/archiver/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", - "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/archiver/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, "node_modules/aria-query": { "version": "5.3.0", @@ -4443,16 +4623,17 @@ "license": "MIT" }, "node_modules/assert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", - "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", "dev": true, "license": "MIT", "dependencies": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" } }, "node_modules/assertion-error": { @@ -4466,27 +4647,17 @@ } }, "node_modules/ast-v8-to-istanbul": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.5.tgz", - "integrity": "sha512-9SdXjNheSiE8bALAQCQQuT6fgQaoxJh7IRYrRGZ8/9nv8WhJeC1aXAwN8TbaOssGOukUvyvnkgD9+Yuykvl1aA==", + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.10.tgz", + "integrity": "sha512-p4K7vMz2ZSk3wN8l5o3y2bJAoZXT3VuJI5OLTATY/01CYWumWvwkUw0SqDBnNq6IiTO3qDa1eSQDibAV8g7XOQ==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.30", + "@jridgewell/trace-mapping": "^0.3.31", "estree-walker": "^3.0.3", "js-tokens": "^9.0.1" } }, - "node_modules/ast-v8-to-istanbul/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", @@ -4521,7 +4692,6 @@ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">= 0.4" } @@ -4599,6 +4769,28 @@ "require-from-string": "^2.0.2" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/blob": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", @@ -4626,6 +4818,29 @@ "dev": true, "license": "MIT" }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -4707,27 +4922,6 @@ "node": ">= 0.10" } }, - "node_modules/browserify-rsa/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==", - "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" - }, "node_modules/browserify-sign": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", @@ -4749,25 +4943,51 @@ "node": ">= 0.10" } }, - "node_modules/browserify-sign/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==", + "node_modules/browserify-sign/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/browserify-sign/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/browserify-sign/node_modules/readable-stream/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, + "license": "MIT" + }, + "node_modules/browserify-sign/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/browserify-sign/node_modules/string_decoder/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, - "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/browserify-zlib": { @@ -4781,10 +5001,9 @@ } }, "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -4802,7 +5021,7 @@ "license": "MIT", "dependencies": { "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "ieee754": "^1.2.1" } }, "node_modules/buffer-crc32": { @@ -4894,6 +5113,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/canvg": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz", @@ -4914,6 +5143,17 @@ "node": ">=10.0.0" } }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chai": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", @@ -4931,16 +5171,123 @@ "node": ">=18" } }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", "dev": true, "license": "MIT", "engines": { "node": ">= 16" } }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, + "node_modules/chevrotain/node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/cipher-base": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", @@ -4956,26 +5303,55 @@ "node": ">= 0.10" } }, - "node_modules/cipher-base/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==", + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "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" + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.1.tgz", + "integrity": "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^7.1.0", + "string-width": "^8.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", + "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/clone": { "version": "2.1.2", @@ -4986,45 +5362,15 @@ "node": ">=0.8" } }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -5043,12 +5389,34 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, "license": "MIT" }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", + "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, "node_modules/compress-commons": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", @@ -5065,74 +5433,18 @@ "node": ">= 14" } }, - "node_modules/compress-commons/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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.2.1" - } - }, - "node_modules/compress-commons/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/compress-commons/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", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "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, "license": "MIT" }, - "node_modules/compress-commons/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "license": "MIT" }, "node_modules/console-browserify": { "version": "1.2.0", @@ -5147,10 +5459,26 @@ "dev": true, "license": "MIT" }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/core-js": { - "version": "3.45.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.45.1.tgz", - "integrity": "sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==", + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.47.0.tgz", + "integrity": "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5165,6 +5493,15 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "license": "MIT", + "dependencies": { + "layout-base": "^1.0.0" + } + }, "node_modules/crc-32": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", @@ -5190,75 +5527,6 @@ "node": ">= 14" } }, - "node_modules/crc32-stream/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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.2.1" - } - }, - "node_modules/crc32-stream/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/crc32-stream/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", - "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/crc32-stream/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -5314,9 +5582,9 @@ "license": "MIT" }, "node_modules/cropperjs": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.6.1.tgz", - "integrity": "sha512-F4wsi+XkDHCOMrHMYjrTEE4QBOrsHHN5/2VsVAaRq8P7E5z7xQpT75S+f/9WikmBEailas3+yo+6zPIomW+NOA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.6.2.tgz", + "integrity": "sha512-nhymn9GdnV3CqiEHJVai54TULFAE3VshJTXSqSJKa8yXAKyBKDWdhHarnlIPrshJ0WMFTGuFvG02YjLXfPiuOA==", "license": "MIT" }, "node_modules/cross-fetch": { @@ -5399,15 +5667,16 @@ } }, "node_modules/cssstyle": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.1.tgz", - "integrity": "sha512-g5PC9Aiph9eiczFpcgUhd9S4UUO3F+LHGRIi5NUMZ+4xtoIYbHNZwZnWA2JsFGe8OU8nl4WyaEFiZuGuxlutJQ==", + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.6.tgz", + "integrity": "sha512-legscpSpgSAeGEe0TNcai97DKt9Vd9AsAdOL7Uoetb52Ar/8eJm3LIa39qpv8wWzLFlNG4vVvppQM+teaMPj3A==", "dev": true, "license": "MIT", "dependencies": { - "@asamuzakjp/css-color": "^4.0.3", - "@csstools/css-syntax-patches-for-csstree": "^1.0.14", - "css-tree": "^3.1.0" + "@asamuzakjp/css-color": "^4.1.1", + "@csstools/css-syntax-patches-for-csstree": "^1.0.21", + "css-tree": "^3.1.0", + "lru-cache": "^11.2.4" }, "engines": { "node": ">=20" @@ -5417,8 +5686,517 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/cytoscape": { + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", + "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", "license": "MIT", - "peer": true + "peer": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "license": "MIT", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "license": "MIT" + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.13.tgz", + "integrity": "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } }, "node_modules/data-urls": { "version": "6.0.0", @@ -5434,42 +6212,11 @@ "node": ">=20" } }, - "node_modules/data-urls/node_modules/tr46": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", - "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", - "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/data-urls/node_modules/webidl-conversions": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.0.tgz", - "integrity": "sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=20" - } - }, - "node_modules/data-urls/node_modules/whatwg-url": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", - "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "^6.0.0", - "webidl-conversions": "^8.0.0" - }, - "engines": { - "node": ">=20" - } + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "license": "MIT" }, "node_modules/debug": { "version": "4.4.3", @@ -5506,6 +6253,13 @@ "node": ">=6" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -5542,6 +6296,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -5573,11 +6336,24 @@ } }, "node_modules/devalue": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.5.0.tgz", - "integrity": "sha512-69sM5yrHfFLJt0AZ9QqZXGCPfJ7fQjvpln3Rq5+PS03LD32Ost1Q9N+eEnaQwGRIriKkMImXD56ocjQmfjbV3w==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.1.tgz", + "integrity": "sha512-jDwizj+IlEZBunHcOuuFVBnIMPAEHvTsJj0BcIp94xYguLRVBcXO853px/MyIJvbVzWdsGvrRweIUWJw8hBP7A==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, "license": "MIT", - "peer": true + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, "node_modules/dfa": { "version": "1.2.0", @@ -5625,11 +6401,10 @@ } }, "node_modules/dompurify": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", - "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", + "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", "license": "(MPL-2.0 OR Apache-2.0)", - "optional": true, "optionalDependencies": { "@types/trusted-types": "^2.0.7" } @@ -5715,15 +6490,22 @@ } }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "dev": true, "license": "MIT" }, "node_modules/enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", + "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -5734,10 +6516,9 @@ } }, "node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -5746,6 +6527,19 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -5786,17 +6580,10 @@ "node": ">= 0.4" } }, - "node_modules/es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==", - "dev": true, - "license": "MIT" - }, "node_modules/esbuild": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", - "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -5806,42 +6593,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.10", - "@esbuild/android-arm": "0.25.10", - "@esbuild/android-arm64": "0.25.10", - "@esbuild/android-x64": "0.25.10", - "@esbuild/darwin-arm64": "0.25.10", - "@esbuild/darwin-x64": "0.25.10", - "@esbuild/freebsd-arm64": "0.25.10", - "@esbuild/freebsd-x64": "0.25.10", - "@esbuild/linux-arm": "0.25.10", - "@esbuild/linux-arm64": "0.25.10", - "@esbuild/linux-ia32": "0.25.10", - "@esbuild/linux-loong64": "0.25.10", - "@esbuild/linux-mips64el": "0.25.10", - "@esbuild/linux-ppc64": "0.25.10", - "@esbuild/linux-riscv64": "0.25.10", - "@esbuild/linux-s390x": "0.25.10", - "@esbuild/linux-x64": "0.25.10", - "@esbuild/netbsd-arm64": "0.25.10", - "@esbuild/netbsd-x64": "0.25.10", - "@esbuild/openbsd-arm64": "0.25.10", - "@esbuild/openbsd-x64": "0.25.10", - "@esbuild/openharmony-arm64": "0.25.10", - "@esbuild/sunos-x64": "0.25.10", - "@esbuild/win32-arm64": "0.25.10", - "@esbuild/win32-ia32": "0.25.10", - "@esbuild/win32-x64": "0.25.10" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=6" + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" } }, "node_modules/escape-string-regexp": { @@ -5858,286 +6635,140 @@ } }, "node_modules/eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "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, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, "node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=4" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "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, "license": "Apache-2.0", "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/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, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint/node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint/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, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/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, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esm-env": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "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, "license": "BSD-3-Clause", "dependencies": { @@ -6152,7 +6783,6 @@ "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.1.tgz", "integrity": "sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg==", "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } @@ -6161,6 +6791,7 @@ "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, "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" @@ -6173,16 +6804,31 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "license": "MIT" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "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, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/event-target-shim": { "version": "5.0.1", @@ -6193,6 +6839,13 @@ "node": ">=6" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true, + "license": "MIT" + }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -6223,9 +6876,9 @@ } }, "node_modules/expect-type": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", - "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -6244,6 +6897,20 @@ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", "license": "MIT" }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-png": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz", @@ -6261,29 +6928,68 @@ "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", "license": "(MIT AND Zlib)" }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, "node_modules/fflate": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", "license": "MIT" }, + "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, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/flatted": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", @@ -6291,6 +6997,37 @@ "dev": true, "license": "ISC" }, + "node_modules/focus-trap": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.7.1.tgz", + "integrity": "sha512-Pkp8m55GjxBLnhBoT6OXdMvfRr4TjMAKLvFM566zlIryq5plbhaTmLAJWTGR0EkRwLjEte1lCOG9MxF1ipJrOg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "tabbable": "^6.4.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/fontkit": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz", @@ -6340,16 +7077,19 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" + "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": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=12" } }, "node_modules/fsevents": { @@ -6386,6 +7126,19 @@ "node": ">= 0.4" } }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -6445,6 +7198,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", @@ -6469,6 +7235,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/globals": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.0.0.tgz", + "integrity": "sha512-gv5BeD2EssA793rlFWVPMMCqefTlpusw6/2TbAVMy0FzcG8wKJn4O+NqJ4+XWmmwrayJgw5TzrmWjFgmz1XPqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -6488,6 +7267,12 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "license": "MIT" + }, "node_modules/hammerjs": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", @@ -6497,6 +7282,28 @@ "node": ">=0.8.0" } }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "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/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -6563,27 +7370,6 @@ "node": ">= 0.10" } }, - "node_modules/hash-base/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==", - "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" - }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", @@ -6608,12 +7394,59 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/heic2any": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/heic2any/-/heic2any-0.0.4.tgz", "integrity": "sha512-3lLnZiDELfabVH87htnRolZ2iehX9zwpRyGNz22GKXIu0fznlblf0/ftppXKNqS26dqFSeqfIBhAmAj/uSp0cA==", "license": "MIT" }, + "node_modules/highlight.js": { + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -6626,17 +7459,24 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "license": "MIT" + }, "node_modules/html-encoding-sniffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", "dev": true, "license": "MIT", "dependencies": { - "whatwg-encoding": "^3.1.1" + "@exodus/bytes": "^1.6.0" }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, "node_modules/html-escaper": { @@ -6646,6 +7486,17 @@ "dev": true, "license": "MIT" }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/html2canvas": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", @@ -6694,10 +7545,26 @@ "node": ">= 14" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/i18next": { - "version": "25.7.2", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.7.2.tgz", - "integrity": "sha512-58b4kmLpLv1buWUEwegMDUqZVR5J+rT+WTRFaBGL7lxDuJQQ0NrJFrq+eT2N94aYVR1k1Sr13QITNOL88tZCuw==", + "version": "25.7.3", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.7.3.tgz", + "integrity": "sha512-2XaT+HpYGuc2uTExq9TVRhLsso+Dxym6PWaKpn36wfBmTI779OQ7iP/XaZHzrnGyzU4SHpFrTYLKfVyBfAhVNA==", "funding": [ { "type": "individual", @@ -6747,7 +7614,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -6782,18 +7648,64 @@ ], "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, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", "license": "MIT" }, + "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, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/iobuffer": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz", @@ -6817,6 +7729,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -6846,13 +7770,29 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-generator-function": { @@ -6875,6 +7815,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-nan": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", @@ -6892,6 +7844,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -6904,7 +7865,6 @@ "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "^1.0.6" } @@ -6962,10 +7922,24 @@ "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", "license": "MIT" }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, "license": "MIT" }, "node_modules/isexe": { @@ -7009,35 +7983,6 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-report/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/istanbul-lib-source-maps": { "version": "5.0.6", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", @@ -7101,39 +8046,52 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, - "node_modules/jsdom": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.0.1.tgz", - "integrity": "sha512-SNSQteBL1IlV2zqhwwolaG9CwhIhTvVHWg3kTss/cLE7H/X4644mtPQqYvCfsSrGQWt9hSZcgOXX8bOZaMN+kA==", + "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, "license": "MIT", "dependencies": { - "@asamuzakjp/dom-selector": "^6.7.2", - "cssstyle": "^5.3.1", + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.4.0.tgz", + "integrity": "sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@acemir/cssom": "^0.9.28", + "@asamuzakjp/dom-selector": "^6.7.6", + "@exodus/bytes": "^1.6.0", + "cssstyle": "^5.3.4", "data-urls": "^6.0.0", "decimal.js": "^10.6.0", - "html-encoding-sniffer": "^4.0.0", + "html-encoding-sniffer": "^6.0.0", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.6", "is-potential-custom-element-name": "^1.0.1", "parse5": "^8.0.0", - "rrweb-cssom": "^0.8.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^6.0.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^8.0.0", - "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^15.1.0", "ws": "^8.18.3", "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=20" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { "canvas": "^3.0.0" @@ -7144,50 +8102,48 @@ } } }, - "node_modules/jsdom/node_modules/tr46": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", - "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { - "punycode": "^2.3.1" + "universalify": "^2.0.0" }, - "engines": { - "node": ">=20" - } - }, - "node_modules/jsdom/node_modules/webidl-conversions": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.0.tgz", - "integrity": "sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=20" - } - }, - "node_modules/jsdom/node_modules/whatwg-url": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", - "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "^6.0.0", - "webidl-conversions": "^8.0.0" - }, - "engines": { - "node": ">=20" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, "node_modules/jspdf": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.3.tgz", - "integrity": "sha512-eURjAyz5iX1H8BOYAfzvdPfIKK53V7mCpBTe7Kb16PaM8JSXEcUQNBQaiWMI8wY5RvNOPj4GccMjTlfwRBd+oQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.0.0.tgz", + "integrity": "sha512-w12U97Z6edKd2tXDn3LzTLg7C7QLJlx0BPfM3ecjK2BckUl9/81vZ+r5gK4/3KQdhAcEZhENUxRhtgYBj75MqQ==", "license": "MIT", + "peer": true, "dependencies": { - "@babel/runtime": "^7.26.9", + "@babel/runtime": "^7.28.4", "fast-png": "^6.2.0", "fflate": "^0.8.1" }, @@ -7198,6 +8154,15 @@ "html2canvas": "^1.0.0-rc.5" } }, + "node_modules/jspdf-autotable": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/jspdf-autotable/-/jspdf-autotable-5.0.7.tgz", + "integrity": "sha512-2wr7H6liNDBYNwt25hMQwXkEWFOEopgKIvR1Eukuw6Zmprm/ZcnmLTQEjW7Xx3FCbD3v7pflLcnMAv/h1jFDQw==", + "license": "MIT", + "peerDependencies": { + "jspdf": "^2 || ^3 || ^4" + } + }, "node_modules/jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -7210,6 +8175,104 @@ "setimmediate": "^1.0.5" } }, + "node_modules/jszip/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/jszip/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==", + "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/jszip/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==", + "license": "MIT" + }, + "node_modules/jszip/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==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/katex": { + "version": "0.16.27", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.27.tgz", + "integrity": "sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" + }, + "node_modules/langium": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", + "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "license": "MIT", + "dependencies": { + "chevrotain": "~11.0.3", + "chevrotain-allstar": "~0.3.0", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.0.8" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "license": "MIT" + }, "node_modules/lazystream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", @@ -7222,6 +8285,56 @@ "node": ">= 0.6.3" } }, + "node_modules/lazystream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/lazystream/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==", + "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/lazystream/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==", + "license": "MIT" + }, + "node_modules/lazystream/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==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lie": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", @@ -7499,25 +8612,134 @@ "node": ">= 0.4" } }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lint-staged": { + "version": "16.2.7", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.2.7.tgz", + "integrity": "sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^14.0.2", + "listr2": "^9.0.5", + "micromatch": "^4.0.8", + "nano-spawn": "^2.0.0", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.8.1" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/listr2": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", + "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/locate-character": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "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, "license": "MIT", "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { @@ -7526,6 +8748,107 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.17.22", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz", + "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/loupe": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", @@ -7533,6 +8856,16 @@ "dev": true, "license": "MIT" }, + "node_modules/lru-cache": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/lucide": { "version": "0.546.0", "resolved": "https://registry.npmjs.org/lucide/-/lucide-0.546.0.tgz", @@ -7570,6 +8903,129 @@ "source-map-js": "^1.2.0" } }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "license": "MIT", + "peer": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-abbr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-abbr/-/markdown-it-abbr-2.0.0.tgz", + "integrity": "sha512-of7C8pXSjXjDojW4neNP+jD7inUYH/DO0Ca+K/4FUEccg0oHAEX/nfscw0jfz66PJbYWOAT9U8mjO21X5p6aAw==", + "license": "MIT" + }, + "node_modules/markdown-it-anchor": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-9.2.0.tgz", + "integrity": "sha512-sa2ErMQ6kKOA4l31gLGYliFQrMKkqSO0ZJgGhDHKijPf0pNFM9vghjAh3gn26pS4JDRs7Iwa9S36gxm3vgZTzg==", + "license": "Unlicense", + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/markdown-it-deflist": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-deflist/-/markdown-it-deflist-3.0.0.tgz", + "integrity": "sha512-OxPmQ/keJZwbubjiQWOvKLHwpV2wZ5I3Smc81OjhwbfJsjdRrvD5aLTQxmZzzePeO0kbGzAo3Krk4QLgA8PWLg==", + "license": "MIT" + }, + "node_modules/markdown-it-emoji": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-3.0.0.tgz", + "integrity": "sha512-+rUD93bXHubA4arpEZO3q80so0qgoFJEKRkRbjKX8RTdca89v2kfyF+xR3i2sQTwql9tpPZPOQN5B+PunspXRg==", + "license": "MIT" + }, + "node_modules/markdown-it-footnote": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-footnote/-/markdown-it-footnote-4.0.0.tgz", + "integrity": "sha512-WYJ7urf+khJYl3DqofQpYfEYkZKbmXmwxQV8c8mO/hGIhgZ1wOe7R4HLFNwqx7TjILbnC98fuyeSsin19JdFcQ==", + "license": "MIT" + }, + "node_modules/markdown-it-ins": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-ins/-/markdown-it-ins-4.0.0.tgz", + "integrity": "sha512-sWbjK2DprrkINE4oYDhHdCijGT+MIDhEupjSHLXe5UXeVr5qmVxs/nTUVtgi0Oh/qtF+QKV0tNWDhQBEPxiMew==", + "license": "MIT" + }, + "node_modules/markdown-it-mark": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-mark/-/markdown-it-mark-4.0.0.tgz", + "integrity": "sha512-YLhzaOsU9THO/cal0lUjfMjrqSMPjjyjChYM7oyj4DnyaXEzA8gnW6cVJeyCrCVeyesrY2PlEdUYJSPFYL4Nkg==", + "license": "MIT" + }, + "node_modules/markdown-it-sub": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-sub/-/markdown-it-sub-2.0.0.tgz", + "integrity": "sha512-iCBKgwCkfQBRg2vApy9vx1C1Tu6D8XYo8NvevI3OlwzBRmiMtsJ2sXupBgEA7PPxiDwNni3qIUkhZ6j5wofDUA==", + "license": "MIT" + }, + "node_modules/markdown-it-sup": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-sup/-/markdown-it-sup-2.0.0.tgz", + "integrity": "sha512-5VgmdKlkBd8sgXuoDoxMpiU+BiEt3I49GItBzzw7Mxq9CxvnhE/k09HFli09zgfFDRixDQDfDxi0mgBCXtaTvA==", + "license": "MIT" + }, + "node_modules/markdown-it-task-lists": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz", + "integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==", + "license": "ISC" + }, + "node_modules/markdown-it-toc-done-right": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/markdown-it-toc-done-right/-/markdown-it-toc-done-right-4.2.0.tgz", + "integrity": "sha512-UB/IbzjWazwTlNAX0pvWNlJS8NKsOQ4syrXZQ/C72j+jirrsjVRT627lCaylrKJFBQWfRsPmIVQie8x38DEhAQ==", + "license": "MIT" + }, + "node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -7592,6 +9048,28 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdn-data": { "version": "2.12.2", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", @@ -7599,6 +9077,148 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, + "node_modules/mermaid": { + "version": "11.12.2", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.2.tgz", + "integrity": "sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==", + "license": "MIT", + "dependencies": { + "@braintree/sanitize-url": "^7.1.1", + "@iconify/utils": "^3.0.1", + "@mermaid-js/parser": "^0.6.3", + "@types/d3": "^7.4.3", + "cytoscape": "^3.29.3", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.13", + "dayjs": "^1.11.18", + "dompurify": "^3.2.5", + "katex": "^0.16.22", + "khroma": "^2.1.0", + "lodash-es": "^4.17.21", + "marked": "^16.2.1", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -7620,6 +9240,19 @@ "dev": true, "license": "MIT" }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -7634,6 +9267,29 @@ "dev": true, "license": "MIT" }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "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/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -7643,6 +9299,32 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/minisearch": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", + "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", + "dev": true, + "license": "MIT" + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, + "license": "MIT" + }, + "node_modules/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" + } + }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -7660,6 +9342,19 @@ "dev": true, "license": "MIT" }, + "node_modules/nano-spawn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-2.0.0.tgz", + "integrity": "sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1" + } + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -7678,6 +9373,20 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -7698,6 +9407,37 @@ } } }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-forge": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz", + "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, "node_modules/node-stdlib-browser": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-stdlib-browser/-/node-stdlib-browser-1.3.1.tgz", @@ -7737,92 +9477,29 @@ "node": ">=10" } }, - "node_modules/node-stdlib-browser/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==", + "node_modules/node-stdlib-browser/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": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/node-stdlib-browser/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, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/node-stdlib-browser/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, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/node-stdlib-browser/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, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/node-stdlib-browser/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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/node-stdlib-browser/node_modules/pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^5.0.0" - }, - "engines": { - "node": ">=10" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "node_modules/node-stdlib-browser/node_modules/punycode": { @@ -7896,6 +9573,55 @@ "node": ">= 0.4" } }, + "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, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/oniguruma-to-es": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz", + "integrity": "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex-xs": "^1.0.0", + "regex": "^6.0.1", + "regex-recursion": "^6.0.2" + } + }, "node_modules/opencollective-postinstall": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", @@ -7905,6 +9631,24 @@ "opencollective-postinstall": "index.js" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -7912,18 +9656,87 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "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", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "license": "BlueOak-1.0.0" }, + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "license": "MIT" + }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "license": "(MIT AND Zlib)" }, + "node_modules/papaparse": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.5.3.tgz", + "integrity": "sha512-5QvjGxYVjxO59MGU2lHVYpRWBBtKHnlIAcSe1uNFCkkptUh63NFRj0FJQm7nR67puEruUci/ZkjmEFrjCAyP4A==", + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-asn1": { "version": "5.1.9", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", @@ -7941,27 +9754,6 @@ "node": ">= 0.10" } }, - "node_modules/parse-asn1/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==", - "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" - }, "node_modules/parse5": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", @@ -7975,6 +9767,19 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -7982,6 +9787,22 @@ "dev": true, "license": "MIT" }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -8024,7 +9845,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, "license": "MIT" }, "node_modules/pathval": { @@ -8055,26 +9875,14 @@ "node": ">= 0.10" } }, - "node_modules/pbkdf2/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==", - "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" + "node_modules/pdf-fontkit": { + "version": "1.8.9", + "resolved": "https://registry.npmjs.org/pdf-fontkit/-/pdf-fontkit-1.8.9.tgz", + "integrity": "sha512-TTq+umfhlFjUuQYOq6dCKT/wLslCrX4zVr5gqrIvrGHfo+vJ3ETapZTb4YLOCErohX7pF+HxlXSZuiToSRhNmA==", + "license": "MIT", + "dependencies": { + "pako": "^1.0.6" + } }, "node_modules/pdf-lib": { "version": "1.17.1", @@ -8089,15 +9897,15 @@ } }, "node_modules/pdfjs-dist": { - "version": "5.4.296", - "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.4.296.tgz", - "integrity": "sha512-DlOzet0HO7OEnmUmB6wWGJrrdvbyJKftI1bhMitK7O2N8W2gc757yyYBbINy9IDafXAV9wmKr9t7xsTaNKRG5Q==", + "version": "5.4.530", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.4.530.tgz", + "integrity": "sha512-r1hWsSIGGmyYUAHR26zSXkxYWLXLMd6AwqcaFYG9YUZ0GBf5GvcjJSeo512tabM4GYFhxhl5pMCmPr7Q72Rq2Q==", "license": "Apache-2.0", "engines": { "node": ">=20.16.0 || >=22.3.0" }, "optionalDependencies": { - "@napi-rs/canvas": "^0.1.80" + "@napi-rs/canvas": "^0.1.84" } }, "node_modules/pdfkit": { @@ -8113,6 +9921,13 @@ "png-js": "^1.0.0" } }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true, + "license": "MIT" + }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -8127,22 +9942,75 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "license": "MIT", "engines": { - "node": ">=12" + "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, "node_modules/png-js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==" }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "license": "MIT" + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "license": "MIT", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, "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", @@ -8153,6 +10021,12 @@ "node": ">= 0.4" } }, + "node_modules/postal-mime": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/postal-mime/-/postal-mime-2.7.1.tgz", + "integrity": "sha512-0VslL0CLSV7PBmglwWR8eCGC5fgsdVictjOG4PEA+vvA0+QJF5SC0tV018CbvAcW4XbpbMIJNd91Dt8vTa9kbA==", + "license": "MIT-0" + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -8172,7 +10046,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -8183,27 +10056,30 @@ } }, "node_modules/preact": { - "version": "10.28.0", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.0.tgz", - "integrity": "sha512-rytDAoiXr3+t6OIP3WGlDd0ouCUG1iCWzkcY3++Nreuoi17y6T5i/zRhe6uYfoVcxq6YU+sBtJouuRDsq8vvqA==", + "version": "10.28.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.2.tgz", + "integrity": "sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA==", "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" } }, "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "dev": true, "license": "MIT", "bin": { @@ -8259,6 +10135,17 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", @@ -8291,10 +10178,19 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -8348,26 +10244,30 @@ } }, "node_modules/react": { - "version": "19.2.1", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", - "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "19.2.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", - "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", "peer": true, "dependencies": { - "scheduler": "^0.27.0" + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "^19.2.1" + "react": "^18.3.1" } }, "node_modules/react-is": { @@ -8378,18 +10278,19 @@ "license": "MIT" }, "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==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", "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" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/readdir-glob": { @@ -8422,12 +10323,51 @@ "node": ">=10" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", "license": "MIT" }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "dev": true, + "license": "MIT" + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -8439,13 +10379,13 @@ } }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -8459,12 +10399,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/restructure": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz", "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==", "license": "MIT" }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, "node_modules/rgbcolor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", @@ -8505,11 +10479,126 @@ "node": ">= 0.8" } }, - "node_modules/ripemd160/node_modules/safe-buffer": { + "node_modules/ripemd160/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/ripemd160/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/ripemd160/node_modules/readable-stream/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, + "license": "MIT" + }, + "node_modules/ripemd160/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/ripemd160/node_modules/string_decoder/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, + "license": "MIT" + }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "license": "Unlicense" + }, + "node_modules/rollup": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", + "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.55.1", + "@rollup/rollup-android-arm64": "4.55.1", + "@rollup/rollup-darwin-arm64": "4.55.1", + "@rollup/rollup-darwin-x64": "4.55.1", + "@rollup/rollup-freebsd-arm64": "4.55.1", + "@rollup/rollup-freebsd-x64": "4.55.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", + "@rollup/rollup-linux-arm-musleabihf": "4.55.1", + "@rollup/rollup-linux-arm64-gnu": "4.55.1", + "@rollup/rollup-linux-arm64-musl": "4.55.1", + "@rollup/rollup-linux-loong64-gnu": "4.55.1", + "@rollup/rollup-linux-loong64-musl": "4.55.1", + "@rollup/rollup-linux-ppc64-gnu": "4.55.1", + "@rollup/rollup-linux-ppc64-musl": "4.55.1", + "@rollup/rollup-linux-riscv64-gnu": "4.55.1", + "@rollup/rollup-linux-riscv64-musl": "4.55.1", + "@rollup/rollup-linux-s390x-gnu": "4.55.1", + "@rollup/rollup-linux-x64-gnu": "4.55.1", + "@rollup/rollup-linux-x64-musl": "4.55.1", + "@rollup/rollup-openbsd-x64": "4.55.1", + "@rollup/rollup-openharmony-arm64": "4.55.1", + "@rollup/rollup-win32-arm64-msvc": "4.55.1", + "@rollup/rollup-win32-ia32-msvc": "4.55.1", + "@rollup/rollup-win32-x64-gnu": "4.55.1", + "@rollup/rollup-win32-x64-msvc": "4.55.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "license": "MIT", + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause" + }, + "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==", - "dev": true, "funding": [ { "type": "github", @@ -8526,61 +10615,6 @@ ], "license": "MIT" }, - "node_modules/rollup": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.4.tgz", - "integrity": "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.52.4", - "@rollup/rollup-android-arm64": "4.52.4", - "@rollup/rollup-darwin-arm64": "4.52.4", - "@rollup/rollup-darwin-x64": "4.52.4", - "@rollup/rollup-freebsd-arm64": "4.52.4", - "@rollup/rollup-freebsd-x64": "4.52.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.52.4", - "@rollup/rollup-linux-arm-musleabihf": "4.52.4", - "@rollup/rollup-linux-arm64-gnu": "4.52.4", - "@rollup/rollup-linux-arm64-musl": "4.52.4", - "@rollup/rollup-linux-loong64-gnu": "4.52.4", - "@rollup/rollup-linux-ppc64-gnu": "4.52.4", - "@rollup/rollup-linux-riscv64-gnu": "4.52.4", - "@rollup/rollup-linux-riscv64-musl": "4.52.4", - "@rollup/rollup-linux-s390x-gnu": "4.52.4", - "@rollup/rollup-linux-x64-gnu": "4.52.4", - "@rollup/rollup-linux-x64-musl": "4.52.4", - "@rollup/rollup-openharmony-arm64": "4.52.4", - "@rollup/rollup-win32-arm64-msvc": "4.52.4", - "@rollup/rollup-win32-ia32-msvc": "4.52.4", - "@rollup/rollup-win32-x64-gnu": "4.52.4", - "@rollup/rollup-win32-x64-msvc": "4.52.4", - "fsevents": "~2.3.2" - } - }, - "node_modules/rrweb-cssom": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", - "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", - "dev": true, - "license": "MIT" - }, - "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==", - "license": "MIT" - }, "node_modules/safe-regex-test": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", @@ -8603,7 +10637,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, "license": "MIT" }, "node_modules/saxes": { @@ -8620,29 +10653,35 @@ } }, "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/search-insights": { + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", + "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", + "dev": true, "license": "MIT", "peer": true }, "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.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "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", @@ -8688,27 +10727,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sha.js/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==", - "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" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -8730,6 +10748,23 @@ "node": ">=8" } }, + "node_modules/shiki": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-2.5.0.tgz", + "integrity": "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/langs": "2.5.0", + "@shikijs/themes": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -8813,6 +10848,18 @@ "dev": true, "license": "ISC" }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/sirv": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", @@ -8828,11 +10875,42 @@ "node": ">=18" } }, + "node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/sortablejs": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.6.tgz", "integrity": "sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/source-map": { "version": "0.6.1", @@ -8862,6 +10940,27 @@ "source-map": "^0.6.0" } }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -8880,9 +10979,9 @@ } }, "node_modules/std-env": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", - "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "dev": true, "license": "MIT" }, @@ -8952,26 +11051,39 @@ } }, "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==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" } }, "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/string-width-cjs": { @@ -8989,7 +11101,22 @@ "node": ">=8" } }, - "node_modules/strip-ansi": { + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", @@ -9001,6 +11128,36 @@ "node": ">=8" } }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/strip-ansi-cjs": { "name": "strip-ansi", "version": "6.0.1", @@ -9014,6 +11171,31 @@ "node": ">=8" } }, + "node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-literal": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", @@ -9034,6 +11216,25 @@ "dev": true, "license": "MIT" }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "license": "MIT" + }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -9061,9 +11262,9 @@ } }, "node_modules/svelte": { - "version": "5.45.5", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.45.5.tgz", - "integrity": "sha512-2074U+vObO5Zs8/qhxtBwdi6ZXNIhEBTzNmUFjiZexLxTdt9vq96D/0pnQELl6YcpLMD7pZ2dhXKByfGS8SAdg==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.46.1.tgz", + "integrity": "sha512-ynjfCHD3nP2el70kN5Pmg37sSi0EjOm9FgHYQdC4giWG/hzO3AatzXXJJgP305uIhGQxSufJLuYWtkY8uK/8RA==", "license": "MIT", "peer": true, "dependencies": { @@ -9092,7 +11293,6 @@ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">= 0.4" } @@ -9114,10 +11314,17 @@ "dev": true, "license": "MIT" }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "dev": true, + "license": "MIT" + }, "node_modules/tailwindcss": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.15.tgz", - "integrity": "sha512-k2WLnWkYFkdpRv+Oby3EBXIyQC8/s1HOFMBUViwtAh6Z5uAozeUSMQlIsn/c6Q2iJzqG6aJT3wdPaRNj70iYxQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", + "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", "license": "MIT" }, "node_modules/tapable": { @@ -9145,9 +11352,9 @@ } }, "node_modules/terser": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz", - "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", "license": "BSD-2-Clause", "peer": true, "dependencies": { @@ -9163,6 +11370,12 @@ "node": ">=10" } }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, "node_modules/tesseract.js": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-6.0.1.tgz", @@ -9182,9 +11395,9 @@ } }, "node_modules/tesseract.js-core": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-6.0.0.tgz", - "integrity": "sha512-1Qncm/9oKM7xgrQXZXNB+NRh19qiXGhxlrR8EwFbK5SaUbPZnS5OMtP/ghtqfd23hsr1ZvZbZjeuAGcMxd/ooA==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-6.1.2.tgz", + "integrity": "sha512-pv4GjmramjdObhDyR1q85Td8X60Puu/lGQn7Kw2id05LLgHhAcWgnz6xSdMCSxBMWjQDmMyDXPTC2aqADdpiow==", "license": "Apache-2.0" }, "node_modules/test-exclude": { @@ -9247,13 +11460,13 @@ } }, "node_modules/tiff": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/tiff/-/tiff-7.1.2.tgz", - "integrity": "sha512-E5rXZJJc3Il0eR4u30PLE6R8DOx/IFyjgS1JhyYvKSEVAAHLTXVwGgZRmLE//K8Pt8d+y4M0Xae30wNGb9Qmxg==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/tiff/-/tiff-7.1.3.tgz", + "integrity": "sha512-YEEq3fT++2pdta/9P/vGG4QRMdZQoe6W6JNaWnIi6NvAsbeNITwFCtmWwL/BZvOi+uo2I3ohyOkD3sZfme+c6g==", "license": "MIT", "dependencies": { - "iobuffer": "^6.0.0", - "pako": "^2.1.0" + "fflate": "^0.8.2", + "iobuffer": "^6.0.0" } }, "node_modules/tiff/node_modules/iobuffer": { @@ -9262,12 +11475,6 @@ "integrity": "sha512-SZWYkWNfjIXIBYSDpXDYIgshqtbOPsi4lviawAEceR1Kqk+sHDlcQjWrzNQsii80AyBY0q5c8HCTNjqo74ul+Q==", "license": "MIT" }, - "node_modules/tiff/node_modules/pako": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", - "license": "(MIT AND Zlib)" - }, "node_modules/timers-browserify": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", @@ -9295,11 +11502,13 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true, - "license": "MIT" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/tinyglobby": { "version": "0.2.15", @@ -9317,6 +11526,36 @@ "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==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tinypool": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", @@ -9348,22 +11587,22 @@ } }, "node_modules/tldts": { - "version": "7.0.17", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.17.tgz", - "integrity": "sha512-Y1KQBgDd/NUc+LfOtKS6mNsC9CCaH+m2P1RoIZy7RAPo3C3/t8X45+zgut31cRZtZ3xKPjfn3TkGTrctC2TQIQ==", + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.19.tgz", + "integrity": "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^7.0.17" + "tldts-core": "^7.0.19" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.0.17", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.17.tgz", - "integrity": "sha512-DieYoGrP78PWKsrXr8MZwtQ7GLCUeLxihtjC1jZsW1DnvSMdKPitJSe8OSYDM2u5H6g3kWJZpePqkp43TfLh0g==", + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.19.tgz", + "integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==", "dev": true, "license": "MIT" }, @@ -9382,33 +11621,17 @@ "node": ">= 0.4" } }, - "node_modules/to-buffer/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/to-buffer/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==", - "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" + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } }, "node_modules/totalist": { "version": "3.0.1", @@ -9434,10 +11657,50 @@ } }, "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "license": "MIT", + "engines": { + "node": ">=6.10" + } }, "node_modules/tslib": { "version": "1.14.1", @@ -9452,6 +11715,19 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -9482,11 +11758,60 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.51.0.tgz", + "integrity": "sha512-jh8ZuM5oEh2PSdyQG9YAEM1TCGuWenLSuSUhf/irbVUNW9O5FhbFVONviN2TgMTBnUmyHv7E56rYnfLZK6TkiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.51.0", + "@typescript-eslint/parser": "8.51.0", + "@typescript-eslint/typescript-estree": "8.51.0", + "@typescript-eslint/utils": "8.51.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "license": "MIT" + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/undici-types": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.14.0.tgz", - "integrity": "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==", - "devOptional": true, + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "license": "MIT" }, "node_modules/unicode-properties": { @@ -9515,6 +11840,99 @@ "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", "license": "MIT" }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "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, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/url": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", @@ -9574,14 +11992,57 @@ "base64-arraybuffer": "^1.0.2" } }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/vite": { - "version": "7.1.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.11.tgz", - "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz", + "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", "license": "MIT", "peer": true, "dependencies": { - "esbuild": "^0.25.0", + "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", @@ -9672,6 +12133,522 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/vite-plugin-compression": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz", + "integrity": "sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "debug": "^4.3.3", + "fs-extra": "^10.0.0" + }, + "peerDependencies": { + "vite": ">=2.0.0" + } + }, + "node_modules/vite-plugin-handlebars": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vite-plugin-handlebars/-/vite-plugin-handlebars-2.0.0.tgz", + "integrity": "sha512-+J3It0nyhPzx4nT1I+fnWH+jShTEXzm6X0Tgsggdm9IYFD7/eJ6a3ROI13HTe0CVoyaxm/fPxH5HDAKyfz7T0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "handlebars": "^4.7.6", + "vite": "^5.0.0" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/vite-plugin-handlebars/node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, "node_modules/vite-plugin-node-polyfills": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.24.0.tgz", @@ -9689,6 +12666,601 @@ "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/vite-plugin-static-copy": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-3.1.4.tgz", + "integrity": "sha512-iCmr4GSw4eSnaB+G8zc2f4dxSuDjbkjwpuBLLGvQYR9IW7rnDzftnUjOH5p4RYR+d4GsiBqXRvzuFhs5bnzVyw==", + "license": "MIT", + "dependencies": { + "chokidar": "^3.6.0", + "p-map": "^7.0.3", + "picocolors": "^1.1.1", + "tinyglobby": "^0.2.15" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitepress": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.6.4.tgz", + "integrity": "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/css": "3.8.2", + "@docsearch/js": "3.8.2", + "@iconify-json/simple-icons": "^1.2.21", + "@shikijs/core": "^2.1.0", + "@shikijs/transformers": "^2.1.0", + "@shikijs/types": "^2.1.0", + "@types/markdown-it": "^14.1.2", + "@vitejs/plugin-vue": "^5.2.1", + "@vue/devtools-api": "^7.7.0", + "@vue/shared": "^3.5.13", + "@vueuse/core": "^12.4.0", + "@vueuse/integrations": "^12.4.0", + "focus-trap": "^7.6.4", + "mark.js": "8.11.1", + "minisearch": "^7.1.1", + "shiki": "^2.1.0", + "vite": "^5.4.14", + "vue": "^3.5.13" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4", + "postcss": "^8" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, + "node_modules/vitepress/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitepress/node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/vitepress/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/vitepress/node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, "node_modules/vitest": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", @@ -9763,6 +13335,26 @@ } } }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest/node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, "node_modules/vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -9770,18 +13362,67 @@ "dev": true, "license": "MIT" }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "license": "MIT" + }, "node_modules/vue": { - "version": "3.5.25", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.25.tgz", - "integrity": "sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g==", + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.26.tgz", + "integrity": "sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==", "license": "MIT", "peer": true, "dependencies": { - "@vue/compiler-dom": "3.5.25", - "@vue/compiler-sfc": "3.5.25", - "@vue/runtime-dom": "3.5.25", - "@vue/server-renderer": "3.5.25", - "@vue/shared": "3.5.25" + "@vue/compiler-dom": "3.5.26", + "@vue/compiler-sfc": "3.5.26", + "@vue/runtime-dom": "3.5.26", + "@vue/server-renderer": "3.5.26", + "@vue/shared": "3.5.26" }, "peerDependencies": { "typescript": "*" @@ -9812,22 +13453,13 @@ "license": "Apache-2.0" }, "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", "dev": true, - "license": "MIT", - "dependencies": { - "iconv-lite": "0.6.3" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/whatwg-mimetype": { @@ -9841,13 +13473,17 @@ } }, "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", + "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", + "dev": true, "license": "MIT", "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.0" + }, + "engines": { + "node": ">=20" } }, "node_modules/which": { @@ -9904,6 +13540,40 @@ "node": ">=8" } }, + "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, + "license": "MIT", + "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/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", @@ -9922,6 +13592,59 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/ws": { "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", @@ -9944,6 +13667,18 @@ } } }, + "node_modules/xlsx": { + "version": "0.20.2", + "resolved": "file:vendor/sheetjs/xlsx-0.20.2.tgz", + "integrity": "sha512-+nKZ39+nvK7Qq6i0PvWWRA4j/EkfWOtkP/YhMtupm+lJIiHxUrgTr1CcKv1nBk1rHtkRRQ3O2+Ih/q/sA+FXZA==", + "license": "Apache-2.0", + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/xml-name-validator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", @@ -9971,6 +13706,22 @@ "node": ">=0.4" } }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "devOptional": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -9984,12 +13735,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zgapdfsigner": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/zgapdfsigner/-/zgapdfsigner-2.7.5.tgz", + "integrity": "sha512-MXVFjyyhb2RSYf1f+JXFBllH7EVZI4V/wS6nMxXJwtqgve4GplkX7gPkpVoByhKdFRIX8JB4hSP4w65d7gT/zg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "1.15.6", + "node-forge": "1.3.1", + "pdf-fontkit": "1.8.9", + "pdf-lib": "1.17.1" + } + }, "node_modules/zimmerframe": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz", "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/zip-stream": { "version": "6.0.1", @@ -10005,75 +13767,6 @@ "node": ">= 14" } }, - "node_modules/zip-stream/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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.2.1" - } - }, - "node_modules/zip-stream/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/zip-stream/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", - "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/zip-stream/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/zlibjs": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/zlibjs/-/zlibjs-0.3.1.tgz", @@ -10082,6 +13775,26 @@ "engines": { "node": "*" } + }, + "node_modules/zod": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz", + "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 549f22c..b32510c 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,18 @@ { "name": "bento-pdf", "private": true, - "version": "1.11.2", - "license": "Apache-2.0", + "version": "1.16.1", + "license": "AGPL-3.0-only", "type": "module", "scripts": { "dev": "vite", - "build": "tsc && vite build", + "build": "tsc && vite build && NODE_OPTIONS='--max-old-space-size=4096' node scripts/generate-i18n-pages.mjs && node scripts/generate-sitemap.mjs", + "build:with-docs": "npm run build && npm run docs:build && node scripts/include-docs-in-dist.js", + "build:gzip": "COMPRESSION_MODE=g npm run build", + "build:brotli": "COMPRESSION_MODE=b npm run build", + "build:original": "COMPRESSION_MODE=o npm run build", + "build:all": "COMPRESSION_MODE=all npm run build", + "build:production": "VITE_USE_CDN=true npm run build:with-docs", "preview": "vite preview", "obfuscate": "node scripts/build.mjs", "test": "vitest", @@ -22,9 +28,16 @@ "release:major": "node scripts/release.js major", "serve:simple": "SIMPLE_MODE=true npm run build && npm run preview -- --port 3000", "serve": "npm run build && npm run preview -- --port 3000", - "package": "node scripts/package-dist.js" + "package": "node scripts/package-dist.js", + "docs:dev": "vitepress dev docs", + "docs:build": "vitepress build docs", + "docs:preview": "vitepress preview docs", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "prepare": "husky" }, "devDependencies": { + "@eslint/js": "^9.39.2", "@testing-library/dom": "^10.4.1", "@types/blob-stream": "^0.1.33", "@types/html2canvas": "^1.0.0", @@ -33,14 +46,26 @@ "@types/utif": "^3.0.6", "@vitest/coverage-v8": "^3.2.4", "@vitest/ui": "^3.2.4", + "eslint": "^9.39.2", + "eslint-config-prettier": "^10.1.8", + "globals": "^17.0.0", + "husky": "^9.1.7", "jsdom": "^27.0.1", + "lint-staged": "^16.2.7", "prettier": "^3.6.2", "typescript": "~5.9.3", + "typescript-eslint": "^8.51.0", "vite": "^7.1.11", + "vite-plugin-compression": "^0.5.1", + "vite-plugin-handlebars": "^2.0.0", "vite-plugin-node-polyfills": "^0.24.0", - "vitest": "^3.2.4" + "vitepress": "^1.6.4", + "vitest": "^3.2.4", + "vue": "^3.5.26" }, "dependencies": { + "@bentopdf/gs-wasm": "^0.1.0", + "@bentopdf/pymupdf-wasm": "^0.11.12", "@fontsource/cedarville-cursive": "^5.2.7", "@fontsource/dancing-script": "^5.2.8", "@fontsource/dm-sans": "^5.2.8", @@ -48,29 +73,70 @@ "@fontsource/kalam": "^5.2.8", "@fontsource/lato": "^5.2.7", "@fontsource/merriweather": "^5.2.11", + "@kenjiuno/msgreader": "^1.27.1-alpha.1", + "@matbee/libreoffice-converter": "^2.3.1", "@neslinesli93/qpdf-wasm": "^0.3.0", "@pdf-lib/fontkit": "^1.1.1", + "@phosphor-icons/web": "^2.1.2", "@tailwindcss/vite": "^4.1.15", + "@types/markdown-it": "^14.1.2", + "@types/node-forge": "^1.3.14", + "@types/papaparse": "^5.5.2", "archiver": "^7.0.1", "blob-stream": "^0.1.3", "cropperjs": "^1.6.1", + "embedpdf-snippet": "file:vendor/embedpdf/embedpdf-snippet-1.5.0.tgz", "heic2any": "^0.0.4", + "highlight.js": "^11.11.1", "html2canvas": "^1.4.1", "i18next": "^25.7.2", "i18next-browser-languagedetector": "^8.2.0", "i18next-http-backend": "^3.0.2", - "jspdf": "^3.0.3", + "jspdf": "^4.0.0", + "jspdf-autotable": "^5.0.2", "jszip": "^3.10.1", "lucide": "^0.546.0", + "markdown-it": "^14.1.0", + "markdown-it-abbr": "^2.0.0", + "markdown-it-anchor": "^9.2.0", + "markdown-it-deflist": "^3.0.0", + "markdown-it-emoji": "^3.0.0", + "markdown-it-footnote": "^4.0.0", + "markdown-it-ins": "^4.0.0", + "markdown-it-mark": "^4.0.0", + "markdown-it-sub": "^2.0.0", + "markdown-it-sup": "^2.0.0", + "markdown-it-task-lists": "^2.1.1", + "markdown-it-toc-done-right": "^4.2.0", + "mermaid": "^11.12.2", + "node-forge": "^1.3.3", + "papaparse": "^5.5.3", "pdf-lib": "^1.17.1", "pdfjs-dist": "^5.4.296", "pdfkit": "^0.17.2", + "postal-mime": "^2.7.1", "sortablejs": "^1.15.6", "tailwindcss": "^4.1.14", "terser": "^5.44.0", "tesseract.js": "^6.0.1", "tiff": "^7.1.2", "utif": "^3.1.0", - "embedpdf-snippet": "file:vendor/embedpdf/embedpdf-snippet-1.5.0.tgz" + "vite-plugin-static-copy": "^3.1.4", + "xlsx": "file:vendor/sheetjs/xlsx-0.20.2.tgz", + "zgapdfsigner": "^2.7.5" + }, + "lint-staged": { + "*.{js,ts,mjs,cjs}": [ + "eslint --fix", + "prettier --write" + ], + "*.{json,md,html,css}": [ + "prettier --write" + ] + }, + "overrides": { + "node-forge": "^1.3.3", + "react": "^18.3.1", + "react-dom": "^18.3.1" } } diff --git a/pdf-converter.html b/pdf-converter.html new file mode 100644 index 0000000..eb02e3d --- /dev/null +++ b/pdf-converter.html @@ -0,0 +1,545 @@ + + + + + + + + PDF Converter - Free Online PDF Converter Tools | BentoPDF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{> navbar }} + + +
+
+

+ PDF Converter - Free Online PDF Conversion Tools +

+

+ Convert your PDFs to and from 40+ different file formats with + BentoPDF's comprehensive conversion tools. Transform PDFs to Word, + Excel, images, text, and many other formats - or convert files into + PDFs. All conversions happen locally in your browser, ensuring + complete privacy. No file uploads, no cloud processing, completely + free. +

+
+
+ + +
+

+ All PDF Converter Tools +

+ +
+ + +

Word to PDF

+

DOCX, DOC to PDF

+
+ + +

Excel to PDF

+

XLSX, XLS to PDF

+
+ + +

PowerPoint to PDF

+

PPTX, PPT to PDF

+
+ + +

JPG to PDF

+

Convert images

+
+ + +

PNG to PDF

+

Convert images

+
+ + +

Image to PDF

+

Any image to PDF

+
+ + +

WebP to PDF

+

Modern format

+
+ + +

SVG to PDF

+

Vector to PDF

+
+ + +

HEIC to PDF

+

iPhone photos

+
+ + +

TIFF to PDF

+

Convert TIFF

+
+ + +

BMP to PDF

+

Convert BMP

+
+ + +

Text to PDF

+

Plain text

+
+ + +

Markdown to PDF

+

MD to PDF

+
+ + +

CSV to PDF

+

Spreadsheet

+
+ + +

JSON to PDF

+

Data to PDF

+
+ + +

PDF to Word

+

Editable DOCX

+
+ + +

PDF to Excel

+

Extract tables

+
+ + +

PDF to JPG

+

Convert to images

+
+ + +

PDF to PNG

+

Convert to images

+
+ + +

PDF to Text

+

Extract text

+
+ + +

PDF to Markdown

+

Extract as MD

+
+ + +

PDF to CSV

+

Extract tables

+
+ + +

PDF to JSON

+

Structured data

+
+ + +

PDF to SVG

+

Vector output

+
+ + +

PDF to WebP

+

Modern format

+
+ + +

PDF to TIFF

+

Convert to TIFF

+
+ + +

PDF to BMP

+

Convert to BMP

+
+ + +

PDF to Greyscale

+

Remove colors

+
+ + +

PDF to PDF/A

+

Archive format

+
+ + +

PDF to ZIP

+

Package files

+
+ + +

ODT to PDF

+

OpenDocument

+
+ + +

ODS to PDF

+

OpenDocument

+
+ + +

ODP to PDF

+

OpenDocument

+
+ + +

ODG to PDF

+

Graphics

+
+ + +

RTF to PDF

+

Rich text

+
+ + +

EPUB to PDF

+

E-book format

+
+ + +

MOBI to PDF

+

Kindle format

+
+ + +

CBZ to PDF

+

Comic archive

+
+ + +

FB2 to PDF

+

FictionBook

+
+ + +

PSD to PDF

+

Photoshop

+
+ + +

XPS to PDF

+

Microsoft XPS

+
+ + +

Pages to PDF

+

Apple Pages

+
+ + +

PUB to PDF

+

Publisher

+
+ + +

VSD to PDF

+

Visio

+
+ + +

WPD to PDF

+

WordPerfect

+
+ + +

WPS to PDF

+

WPS Office

+
+ + +

XML to PDF

+

XML data

+
+
+
+ + +
+
+

+ Why Use BentoPDF PDF Converter Tools? +

+ +
+
+ +

+ 100% Privacy-First +

+

+ All operations happen in your browser. Your files never leave your + device, never uploaded to servers. Complete privacy guaranteed. +

+
+ +
+ +

+ Unlimited & Free +

+

+ Use all tools as many times as you want, with files of any size. + No file limits, no tool limits. Completely free forever. +

+
+ +
+ +

+ Lightning Fast +

+

+ Browser-based processing means instant results. No waiting for + uploads or downloads. Works offline after page load. +

+
+ +
+ +

+ No Signup Required +

+

+ Start using tools immediately. No account creation, no email, no + personal information needed. Just open and use. +

+
+
+
+
+ + +
+
+

+ Frequently Asked Questions +

+ +
+
+ + Are these pdf converter tools really free? + + +

+ Yes! All BentoPDF pdf converter tools are 100% free with no hidden + fees, no premium tiers, and no subscription required. Use + unlimited tools, unlimited times. +

+
+ +
+ + Are my files private and secure? + + +

+ Absolutely! All processing happens entirely in your browser. Your + files never leave your device, are never uploaded to servers. + Complete privacy guaranteed. +

+
+ +
+ + Is there a file size limit? + + +

+ No file size limits! Process files of any size. Browser-based + processing means no artificial limitations. +

+
+ +
+ + Do I need to install software? + + +

+ No installation required! All tools are web-based and work + directly in your browser. Just open the page and start using - + works on any device. +

+
+
+
+
+ + + {{> footer }} + + + + + + + + + + + + + diff --git a/pdf-editor.html b/pdf-editor.html new file mode 100644 index 0000000..0e1a0ad --- /dev/null +++ b/pdf-editor.html @@ -0,0 +1,414 @@ + + + + + + + + PDF Editor - Free Online PDF Editor Tools | BentoPDF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{> navbar }} + + +
+
+

+ PDF Editor - Free Online PDF Editing Tools +

+

+ Edit and enhance your PDF files with BentoPDF's comprehensive suite of + 25+ editing tools. Compress file sizes, rotate pages, crop documents, + add watermarks, insert page numbers, change colors, and much more. All + editing happens in your browser - your files stay completely private. + No signup, no limits, completely free. +

+
+
+ + +
+

+ All PDF Editor Tools +

+ + +
+ + +
+
+

+ Why Use BentoPDF PDF Editor Tools? +

+ +
+
+ +

+ 100% Privacy-First +

+

+ All operations happen in your browser. Your files never leave your + device, never uploaded to servers. Complete privacy guaranteed. +

+
+ +
+ +

+ Unlimited & Free +

+

+ Use all tools as many times as you want, with files of any size. + No file limits, no tool limits. Completely free forever. +

+
+ +
+ +

+ Lightning Fast +

+

+ Browser-based processing means instant results. No waiting for + uploads or downloads. Works offline after page load. +

+
+ +
+ +

+ No Signup Required +

+

+ Start using tools immediately. No account creation, no email, no + personal information needed. Just open and use. +

+
+
+
+
+ + +
+
+

+ Frequently Asked Questions +

+ +
+
+ + Are these pdf editor tools really free? + + +

+ Yes! All BentoPDF pdf editor tools are 100% free with no hidden + fees, no premium tiers, and no subscription required. Use + unlimited tools, unlimited times. +

+
+ +
+ + Are my files private and secure? + + +

+ Absolutely! All processing happens entirely in your browser. Your + files never leave your device, are never uploaded to servers. + Complete privacy guaranteed. +

+
+ +
+ + Is there a file size limit? + + +

+ No file size limits! Process files of any size. Browser-based + processing means no artificial limitations. +

+
+ +
+ + Do I need to install software? + + +

+ No installation required! All tools are web-based and work + directly in your browser. Just open the page and start using - + works on any device. +

+
+
+
+
+ + + {{> footer }} + + + + + + + + + + + + + diff --git a/pdf-merge-split.html b/pdf-merge-split.html new file mode 100644 index 0000000..a250c11 --- /dev/null +++ b/pdf-merge-split.html @@ -0,0 +1,372 @@ + + + + + + + + + PDF Merge & Split - Free Online PDF Merge & Split Tools | BentoPDF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{> navbar }} + + +
+
+

+ PDF Merge & Split Tools - Combine & Separate PDFs Free +

+

+ Combine multiple PDF files into one document or split large PDFs into + smaller files with BentoPDF's merge and split tools. Reorder pages, + extract specific sections, alternate merge documents, and organize + your PDFs exactly how you need them. Browser-based processing ensures + your files stay private. No limits on file count or size. +

+
+
+ + +
+

+ All PDF Merge & Split Tools +

+ + +
+ + +
+
+

+ Why Use BentoPDF PDF Merge & Split Tools? +

+ +
+
+ +

+ 100% Privacy-First +

+

+ All operations happen in your browser. Your files never leave your + device, never uploaded to servers. Complete privacy guaranteed. +

+
+ +
+ +

+ Unlimited & Free +

+

+ Use all tools as many times as you want, with files of any size. + No file limits, no tool limits. Completely free forever. +

+
+ +
+ +

+ Lightning Fast +

+

+ Browser-based processing means instant results. No waiting for + uploads or downloads. Works offline after page load. +

+
+ +
+ +

+ No Signup Required +

+

+ Start using tools immediately. No account creation, no email, no + personal information needed. Just open and use. +

+
+
+
+
+ + +
+
+

+ Frequently Asked Questions +

+ +
+
+ + Are these pdf merge & split tools really free? + + +

+ Yes! All BentoPDF pdf merge & split tools are 100% free with no + hidden fees, no premium tiers, and no subscription required. Use + unlimited tools, unlimited times. +

+
+ +
+ + Are my files private and secure? + + +

+ Absolutely! All processing happens entirely in your browser. Your + files never leave your device, are never uploaded to servers. + Complete privacy guaranteed. +

+
+ +
+ + Is there a file size limit? + + +

+ No file size limits! Process files of any size. Browser-based + processing means no artificial limitations. +

+
+ +
+ + Do I need to install software? + + +

+ No installation required! All tools are web-based and work + directly in your browser. Just open the page and start using - + works on any device. +

+
+
+
+
+ + + {{> footer }} + + + + + + + + + + + + + diff --git a/pdf-security.html b/pdf-security.html new file mode 100644 index 0000000..58db29a --- /dev/null +++ b/pdf-security.html @@ -0,0 +1,349 @@ + + + + + + + + PDF Security - Free Online PDF Security Tools | BentoPDF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{> navbar }} + + +
+
+

+ PDF Security Tools - Protect & Secure Your PDFs Free +

+

+ Protect and secure your PDF documents with BentoPDF's comprehensive + security tools. Encrypt with passwords, add digital signatures, manage + permissions, remove sensitive data, and more. All security operations + happen locally in your browser for maximum privacy. No cloud uploads, + no data retention - your documents stay completely confidential. +

+
+
+ + +
+

+ All PDF Security Tools +

+ + +
+ + +
+
+

+ Why Use BentoPDF PDF Security Tools? +

+ +
+
+ +

+ 100% Privacy-First +

+

+ All operations happen in your browser. Your files never leave your + device, never uploaded to servers. Complete privacy guaranteed. +

+
+ +
+ +

+ Unlimited & Free +

+

+ Use all tools as many times as you want, with files of any size. + No file limits, no tool limits. Completely free forever. +

+
+ +
+ +

+ Lightning Fast +

+

+ Browser-based processing means instant results. No waiting for + uploads or downloads. Works offline after page load. +

+
+ +
+ +

+ No Signup Required +

+

+ Start using tools immediately. No account creation, no email, no + personal information needed. Just open and use. +

+
+
+
+
+ + +
+
+

+ Frequently Asked Questions +

+ +
+
+ + Are these pdf security tools really free? + + +

+ Yes! All BentoPDF pdf security tools are 100% free with no hidden + fees, no premium tiers, and no subscription required. Use + unlimited tools, unlimited times. +

+
+ +
+ + Are my files private and secure? + + +

+ Absolutely! All processing happens entirely in your browser. Your + files never leave your device, are never uploaded to servers. + Complete privacy guaranteed. +

+
+ +
+ + Is there a file size limit? + + +

+ No file size limits! Process files of any size. Browser-based + processing means no artificial limitations. +

+
+ +
+ + Do I need to install software? + + +

+ No installation required! All tools are web-based and work + directly in your browser. Just open the page and start using - + works on any device. +

+
+
+
+
+ + + {{> footer }} + + + + + + + + + + + + + diff --git a/privacy.html b/privacy.html index bddeb00..78de50c 100644 --- a/privacy.html +++ b/privacy.html @@ -1,284 +1,231 @@ + + + + + Privacy Policy - Your Data Stays Private | BentoPDF + + + - - - - Privacy Policy - BentoPDF - - - - - - + + - - + + -
-
-

- Privacy Policy -

-

- Last Updated: September 14, 2025 -

+ + + + + + + -
-
- -
-
-
-
-
- Bento PDF Logo - BentoPDF -
-

- © 2025 BentoPDF. All rights reserved. +

-
-

Company

-
    +

    1.1 The Client-Side Principle

    +

    + Unlike other online PDF services, BentoPDF does not upload your + files to a server for processing. The tools you use are powered by + JavaScript and WebAssembly libraries that run directly on your + device. This means your data never leaves your computer, providing + you with the highest level of privacy and security. +

    + +

    2. Information We Do Not Collect

    +

    + Because of our client-side architecture, we are technically + incapable of collecting the following information: +

    +
    • - About Us + The content of your PDF files or any other documents you use with + our tools.
    • +
    • Any personal data contained within your documents.
    • +
    • Filenames of your documents.
    • - FAQ -
    • -
    • - Contact Us + Any derived information or metadata from your files, beyond what + is necessary for the tool to function during your active session + (and this is immediately discarded).
    -
-
-

Legal

-
    +

    3. Information We May Collect (Non-Personal Data)

    +

    + To improve our website and services, we may collect anonymous, + non-personally identifiable information. This type of data helps us + understand how users interact with our site, which tools are most + popular, and how we can improve the user experience. This includes: +

    +
    • - Licensing + Usage Analytics: Anonymized data such as which + tools are used, how often they are used, and which features are + accessed. This is aggregated and cannot be tied back to an + individual user or document.
    • - Terms and Conditions -
    • -
    • - Privacy Policy + Performance Data: Anonymized error reports or + performance metrics to help us identify and fix bugs. This data + contains no personal information or file content.
    -
+

+ We use privacy-respecting analytics platforms for this purpose. + Specifically, we use + Simple Analytics + to track anonymous visit counts. This means we can see how many + users visit our site, but + we never collect personal information or identify individual + users. Simple Analytics is fully GDPR-compliant and respects user + privacy. We do not use tracking cookies for advertising or + cross-site profiling. +

-
-

Follow Us

- +

4. Third-Party Libraries

+

+ BentoPDF is built using powerful, open-source libraries like + PDF-lib.js and PDF.js. These libraries are trusted by developers + worldwide and operate under the same client-side principle. While we + have vetted these libraries, we encourage you to review their + respective privacy policies for your own peace of mind. +

+ +

5. Security

+

+ Since your files are never transmitted over the internet to our + servers, you are protected from potential data breaches during + transit or storage on a server. The security of your documents is in + your hands and protected by the security of your own computer and + web browser. +

+ +

6. Children's Privacy

+

+ Our services are not directed at individuals under the age of 13. We + do not knowingly collect any personal information from children. If + you believe a child has provided us with personal information, + please contact us, and we will take steps to delete such + information. +

+ +

7. Changes to This Privacy Policy

+

+ We may update this Privacy Policy from time to time. We will notify + you of any changes by posting the new policy on this page and + updating the "Last Updated" date at the top. You are advised to + review this Privacy Policy periodically for any changes. +

+ +

8. Contact Us

+

+ If you have any questions about this Privacy Policy, please contact + us at + contact@bentopdf.com. +

-
+
-
- - - - - - \ No newline at end of file + {{> footer }} + + + + + + + + diff --git a/public/ghostscript-wasm/gs.js b/public/ghostscript-wasm/gs.js new file mode 100644 index 0000000..b2541ea --- /dev/null +++ b/public/ghostscript-wasm/gs.js @@ -0,0 +1,113 @@ +async function Module(moduleArg={}){var moduleRtn;var f=moduleArg,aa="object"==typeof window,ba="undefined"!=typeof WorkerGlobalScope,k="object"==typeof process&&process.versions?.node&&"renderer"!=process.type,ca=!aa&&!k&&!ba;if(k){const {createRequire:a}=await import("module");var require=a(import.meta.url)}var da="./this.program",ea=(a,b)=>{throw b;},ia=import.meta.url,ja="",ka,la; +if(k){if("object"!=typeof process||!process.versions?.node||"renderer"==process.type)throw Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");var ma=process.versions.node,na=ma.split(".").slice(0,3);na=1E4*na[0]+100*na[1]+1*na[2].split("-")[0];if(16E4>na)throw Error("This emscripten-generated code requires node v16.0.0 (detected v"+ma+")");var fs=require("fs"); +ia.startsWith("file:")&&(ja=require("path").dirname(require("url").fileURLToPath(ia))+"/");la=a=>{a=oa(a)?new URL(a):a;a=fs.readFileSync(a);m(Buffer.isBuffer(a));return a};ka=async a=>{a=oa(a)?new URL(a):a;a=fs.readFileSync(a,void 0);m(Buffer.isBuffer(a));return a};1{process.exitCode=a;throw b;}}else if(ca){if("object"==typeof process&&process.versions?.node&&"renderer"!=process.type||"object"==typeof window|| +"undefined"!=typeof WorkerGlobalScope)throw Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");}else if(aa||ba){try{ja=(new URL(".",ia)).href}catch{}if("object"!=typeof window&&"undefined"==typeof WorkerGlobalScope)throw Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)"); +ba&&(la=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)});ka=async a=>{if(oa(a))return new Promise((c,d)=>{var e=new XMLHttpRequest;e.open("GET",a,!0);e.responseType="arraybuffer";e.onload=()=>{200==e.status||0==e.status&&e.response?c(e.response):d(e.status)};e.onerror=d;e.send(null)});var b=await fetch(a,{credentials:"same-origin"});if(b.ok)return b.arrayBuffer();throw Error(b.status+" : "+b.url);}}else throw Error("environment detection error"); +var p=console.log.bind(console),t=console.error.bind(console);m(!ca,"shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.");var pa;"object"!=typeof WebAssembly&&t("no native wasm support detected");var qa=!1,ra;function m(a,b){a||v("Assertion failed"+(b?": "+b:""))}var oa=a=>a.startsWith("file://");function sa(){var a=ta();m(0==(a&3));0==a&&(a+=4);x[a>>2]=34821223;x[a+4>>2]=2310721022;x[0]=1668509029} +function ua(){if(!qa){var a=ta();0==a&&(a+=4);var b=x[a>>2],c=x[a+4>>2];34821223==b&&2310721022==c||v(`Stack overflow! Stack cookie has been overwritten at ${va(a)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${va(c)} ${va(b)}`);1668509029!=x[0]&&v("Runtime error: The application has corrupted its heap memory area (address zero)!")}}var wa=new Int16Array(1),xa=new Int8Array(wa.buffer);wa[0]=25459; +if(115!==xa[0]||99!==xa[1])throw"Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)";function ya(a){Object.getOwnPropertyDescriptor(f,a)||Object.defineProperty(f,a,{configurable:!0,set(){v(`Attempt to set \`Module.${a}\` after it has already been processed. This can happen, for example, when code is injected via '--post-js' rather than '--pre-js'`)}})} +function y(a){return()=>m(!1,`call to '${a}' via reference taken before Wasm module initialization`)}function Aa(a){return"FS_createPath"===a||"FS_createDataFile"===a||"FS_createPreloadedFile"===a||"FS_preloadFile"===a||"FS_unlink"===a||"addRunDependency"===a||"FS_createLazyFile"===a||"FS_createDevice"===a||"removeRunDependency"===a}function Ba(a,b){"undefined"==typeof globalThis||Object.getOwnPropertyDescriptor(globalThis,a)||Object.defineProperty(globalThis,a,{configurable:!0,get(){b()}})} +function Ca(a,b){Ba(a,()=>{z(`\`${a}\` is not longer defined by emscripten. ${b}`)})}Ca("buffer","Please use HEAP8.buffer or wasmMemory.buffer");Ca("asm","Please use wasmExports instead");function Da(a){Object.getOwnPropertyDescriptor(f,a)||Object.defineProperty(f,a,{configurable:!0,get(){var b=`'${a}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`;Aa(a)&&(b+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you");v(b)}})} +var Ea,Fa,Ga,A,Ha,Ia,B,x,C,Ja=!1;function Ka(){var a=Ga.buffer;A=new Int8Array(a);Ia=new Int16Array(a);Ha=new Uint8Array(a);new Uint16Array(a);B=new Int32Array(a);x=new Uint32Array(a);new Float32Array(a);new Float64Array(a);C=new BigInt64Array(a);new BigUint64Array(a)}m("undefined"!=typeof Int32Array&&"undefined"!==typeof Float64Array&&void 0!=Int32Array.prototype.subarray&&void 0!=Int32Array.prototype.set,"JS engine does not provide full typed array support");var E=0,La=null,Ma={},I=null; +function Na(a){E++;f.monitorRunDependencies?.(E);m(a,"addRunDependency requires an ID");m(!Ma[a]);Ma[a]=1;null===I&&"undefined"!=typeof setInterval&&(I=setInterval(()=>{if(qa)clearInterval(I),I=null;else{var b=!1,c;for(c in Ma)b||(b=!0,t("still waiting on run dependencies:")),t(`dependency: ${c}`);b&&t("(end of list)")}},1E4),I.unref?.())} +function Oa(a){E--;f.monitorRunDependencies?.(E);m(a,"removeRunDependency requires an ID");m(Ma[a]);delete Ma[a];0==E&&(null!==I&&(clearInterval(I),I=null),La&&(a=La,La=null,a()))}function v(a){f.onAbort?.(a);a="Aborted("+a+")";t(a);qa=!0;a=new WebAssembly.RuntimeError(a);Fa?.(a);throw a;} +function K(a,b){return(...c)=>{m(Ja,`native function \`${a}\` called before runtime initialization`);var d=L[a];m(d,`exported native function \`${a}\` not found`);m(c.length<=b,`native function \`${a}\` called with ${c.length} args but expects ${b}`);return d(...c)}}var Pa;async function Qa(a){if(!pa)try{var b=await ka(a);return new Uint8Array(b)}catch{}if(a==Pa&&pa)a=new Uint8Array(pa);else if(la)a=la(a);else throw"both async and sync fetching of the wasm failed";return a} +async function Ra(a,b){try{var c=await Qa(a);return await WebAssembly.instantiate(c,b)}catch(d){t(`failed to asynchronously prepare wasm: ${d}`),oa(Pa)&&t(`warning: Loading from a file URI (${Pa}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`),v(d)}} +async function Sa(a){var b=Pa;if(!pa&&!oa(b)&&!k)try{var c=fetch(b,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(c,a)}catch(d){t(`wasm streaming compile failed: ${d}`),t("falling back to ArrayBuffer instantiation")}return Ra(b,a)}class Ta{name="ExitStatus";constructor(a){this.message=`Program terminated with exit(${a})`;this.status=a}} +var Ua=a=>{for(;0{var a=f.preRun.shift();Wa.push(a)},Ya=!0,va=a=>{m("number"===typeof a);return"0x"+(a>>>0).toString(16).padStart(8,"0")},z=a=>{z.$||(z.$={});z.$[a]||(z.$[a]=1,k&&(a="warning: "+a),t(a))},Za="undefined"!=typeof TextDecoder?new TextDecoder:void 0,$a=(a,b=0)=>{var c=b;for(var d=c+void 0;a[c]&&!(c>=d);)++c;if(16e?d+=String.fromCharCode(e):(e-=65536,d+=String.fromCharCode(55296|e>>10,56320|e&1023))}}else d+=String.fromCharCode(e)}return d},M=a=>{m("number"==typeof a,`UTF8ToString expects a number (got ${typeof a})`);return a?$a(Ha,a):""},ab=(a,b)=>{for(var c=0,d=a.length- +1;0<=d;d--){var e=a[d];"."===e?a.splice(d,1):".."===e?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c;c--)a.unshift("..");return a},bb=a=>{var b="/"===a.charAt(0),c="/"===a.slice(-1);(a=ab(a.split("/").filter(d=>!!d),!b).join("/"))||b||(a=".");a&&c&&(a+="/");return(b?"/":"")+a},cb=a=>{var b=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(a).slice(1);a=b[0];b=b[1];if(!a&&!b)return".";b&&=b.slice(0,-1);return a+b},N=a=>a&&a.match(/([^\/]+|\/)\/*$/)[1],db=(a,b)=>bb(a+"/"+ +b),eb=()=>{if(k){var a=require("crypto");return b=>a.randomFillSync(b)}return b=>crypto.getRandomValues(b)},fb=a=>{(fb=eb())(a)},gb=(...a)=>{for(var b="",c=!1,d=a.length-1;-1<=d&&!c;d--){c=0<=d?a[d]:O.cwd();if("string"!=typeof c)throw new TypeError("Arguments to path.resolve must be strings");if(!c)return"";b=c+"/"+b;c="/"===c.charAt(0)}b=ab(b.split("/").filter(e=>!!e),!c).join("/");return(c?"/":"")+b||"."},hb=(a,b)=>{function c(h){for(var l=0;lr?[]:h.slice(l,r-l+1)}a=gb(a).slice(1);b=gb(b).slice(1);a=c(a.split("/"));b=c(b.split("/"));for(var d=Math.min(a.length,b.length),e=d,g=0;g{for(var b=0,c=0;c=d?b++:2047>=d?b+=2:55296<=d&&57343>=d?(b+=4,++c):b+=3}return b},kb=(a,b,c,d)=>{m("string"===typeof a,`stringToUTF8Array expects a string (got ${typeof a})`); +if(!(0=h){if(c>=d)break;b[c++]=h}else if(2047>=h){if(c+1>=d)break;b[c++]=192|h>>6;b[c++]=128|h&63}else if(65535>=h){if(c+2>=d)break;b[c++]=224|h>>12;b[c++]=128|h>>6&63;b[c++]=128|h&63}else{if(c+3>=d)break;1114111>18;b[c++]= +128|h>>12&63;b[c++]=128|h>>6&63;b[c++]=128|h&63;g++}}b[c]=0;return c-e},lb=a=>{var b=Array(jb(a)+1);a=kb(a,b,0,b.length);b.length=a;return b},mb=[];function nb(a,b){mb[a]={input:[],output:[],H:b};ob(a,pb)} +var pb={open(a){var b=mb[a.node.rdev];if(!b)throw new O.g(43);a.tty=b;a.seekable=!1},close(a){a.tty.H.fsync(a.tty)},fsync(a){a.tty.H.fsync(a.tty)},read(a,b,c,d){if(!a.tty||!a.tty.H.ha)throw new O.g(60);for(var e=0,g=0;g{v("internal error: mmapAlloc called but `emscripten_builtin_memalign` native symbol not exported")}, +P={D:null,m(){return P.createNode(null,"/",16895,0)},createNode(a,b,c,d){if(24576===(c&61440)||O.isFIFO(c))throw new O.g(63);P.D||(P.D={dir:{node:{v:P.h.v,B:P.h.B,lookup:P.h.lookup,G:P.h.G,rename:P.h.rename,unlink:P.h.unlink,rmdir:P.h.rmdir,readdir:P.h.readdir,symlink:P.h.symlink},stream:{s:P.i.s}},file:{node:{v:P.h.v,B:P.h.B},stream:{s:P.i.s,read:P.i.read,write:P.i.write,M:P.i.M,P:P.i.P}},link:{node:{v:P.h.v,B:P.h.B,readlink:P.h.readlink},stream:{}},ba:{node:{v:P.h.v,B:P.h.B},stream:O.ta}});c=O.createNode(a, +b,c,d);Q(c.mode)?(c.h=P.D.dir.node,c.i=P.D.dir.stream,c.j={}):O.isFile(c.mode)?(c.h=P.D.file.node,c.i=P.D.file.stream,c.o=0,c.j=null):40960===(c.mode&61440)?(c.h=P.D.link.node,c.i=P.D.link.stream):8192===(c.mode&61440)&&(c.h=P.D.ba.node,c.i=P.D.ba.stream);c.atime=c.mtime=c.ctime=Date.now();a&&(a.j[b]=c,a.atime=a.mtime=a.ctime=c.atime);return c},fb(a){return a.j?a.j.subarray?a.j.subarray(0,a.o):new Uint8Array(a.j):new Uint8Array(0)},h:{v(a){var b={};b.dev=8192===(a.mode&61440)?a.id:1;b.ino=a.id;b.mode= +a.mode;b.nlink=1;b.uid=0;b.gid=0;b.rdev=a.rdev;Q(a.mode)?b.size=4096:O.isFile(a.mode)?b.size=a.o:40960===(a.mode&61440)?b.size=a.link.length:b.size=0;b.atime=new Date(a.atime);b.mtime=new Date(a.mtime);b.ctime=new Date(a.ctime);b.blksize=4096;b.blocks=Math.ceil(b.size/b.blksize);return b},B(a,b){for(var c of["mode","atime","mtime","ctime"])null!=b[c]&&(a[c]=b[c]);void 0!==b.size&&(b=b.size,a.o!=b&&(0==b?(a.j=null,a.o=0):(c=a.j,a.j=new Uint8Array(b),c&&a.j.set(c.subarray(0,Math.min(b,a.o))),a.o=b)))}, +lookup(){throw new O.g(44);},G(a,b,c,d){return P.createNode(a,b,c,d)},rename(a,b,c){try{var d=R(b,c)}catch(g){}if(d){if(Q(a.mode))for(var e in d.j)throw new O.g(55);tb(d)}delete a.parent.j[a.name];b.j[c]=a;a.name=c;b.ctime=b.mtime=a.parent.ctime=a.parent.mtime=Date.now()},unlink(a,b){delete a.j[b];a.ctime=a.mtime=Date.now()},rmdir(a,b){var c=R(a,b),d;for(d in c.j)throw new O.g(55);delete a.j[b];a.ctime=a.mtime=Date.now()},readdir(a){return[".","..",...Object.keys(a.j)]},symlink(a,b,c){a=P.createNode(a, +b,41471,0);a.link=c;return a},readlink(a){if(40960!==(a.mode&61440))throw new O.g(28);return a.link}},i:{read(a,b,c,d,e){var g=a.node.j;if(e>=a.node.o)return 0;a=Math.min(a.node.o-e,d);m(0<=a);if(8=g||(g=Math.max(g,h*(1048576>h?2:1.125)>>>0),0!=h&&(g=Math.max(g,256)),h=a.j,a.j=new Uint8Array(g),0b)throw new O.g(28); +return b},M(a,b,c,d,e){if(!O.isFile(a.node.mode))throw new O.g(43);a=a.node.j;if(e&2||!a||a.buffer!==A.buffer){d=!0;e=sb();if(!e)throw new O.g(48);if(a){if(0{var c=0;a&&(c|=365);b&&(c|=146);return c},vb={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6, +EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118, +ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23, +EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135},wb=async a=>{var b=await ka(a);m(b,`Loading data file "${a}" failed (no arrayBuffer).`);return new Uint8Array(b)},xb=[],zb=async(a,b)=>{"undefined"!=typeof Browser&&yb();for(var c of xb)if(c.canHandle(b))return m("AsyncFunction"=== +c.handle.constructor.name,"Filesystem plugin handlers must be async functions (See #24914)"),c.handle(a,b);return a},Bb=async(a,b,c,d,e,g,h,l)=>{var r=b?gb(bb(a+"/"+b)):a,q;a:for(var u=q=`cp ${r}`;;){if(!Ma[q])break a;q=u+Math.random()}Na(q);try{if(u=c,"string"==typeof c&&(u=await wb(c)),u=await zb(u,r),l?.(),!g){c=u;g=b;a&&(a="string"==typeof a?a:Ab(a),g=b?bb(a+"/"+b):a);var n=ub(d,e),w=O.create(g,n);if(c){if("string"==typeof c){var F=Array(c.length);b=0;for(var G=c.length;bc;c++){a=a.split("/").filter(l=>!!l);for(var d=O.root,e="/",g=0;g>>0)%O.C.length}function Db(a){var b=Cb(a.parent.id,a.name);a.L=O.C[b];O.C[b]=a} +function Eb(a){var b=["r","w","rw"][a&3];a&512&&(b+="w");return b}function S(a,b){if(O.ia)return 0;if(!b.includes("r")||a.mode&292){if(b.includes("w")&&!(a.mode&146)||b.includes("x")&&!(a.mode&73))return 2}else return 2;return 0}function Fb(a,b){if(!Q(a.mode))return 54;try{return R(a,b),20}catch(c){}return S(a,"wx")} +function Gb(a,b,c){try{var d=R(a,b)}catch(e){return e.l}if(a=S(a,"wx"))return a;if(c){if(!Q(d.mode))return 54;if(O.N(d)||Ab(d)===O.cwd())return 10}else if(Q(d.mode))return 31;return 0}function Hb(a,b){if(!a)throw new O.g(b);return a}function U(a){a=O.ga(a);if(!a)throw new O.g(8);return a}function Ib(a,b=-1){m(-1<=b);a=Object.assign(new O.ra,a);if(-1==b)a:{for(b=0;b<=O.aa;b++)if(!O.streams[b])break a;throw new O.g(33);}a.fd=b;return O.streams[b]=a} +function Jb(a,b=-1){a=Ib(a,b);a.i?.Za?.(a);return a}function Kb(a,b,c){var d=a?.i.B;a=d?a:b;d??=b.h.B;Hb(d,63);d(a,c)}function Lb(a){var b=[];for(a=[a];a.length;){var c=a.pop();b.push(c);a.push(...c.O)}return b}function Mb(a){var b={Na:4096,bb:4096,blocks:1E6,Ma:5E5,La:5E5,files:O.Y,$a:O.Y-1,cb:42,flags:2,kb:255};a.h.oa&&Object.assign(b,a.h.oa(a.m.Ea.root));return b}function Nb(a,b,c){"undefined"==typeof c&&(c=b,b=438);return O.G(a,b|8192,c)} +function Ob(a,b,c,d){Kb(a,b,{mode:c&4095|b.mode&-4096,ctime:Date.now(),fa:d})}function Pb(a,b,c){if(Q(b.mode))throw new O.g(31);if(!O.isFile(b.mode))throw new O.g(28);var d=S(b,"w");if(d)throw new O.g(d);Kb(a,b,{size:c,timestamp:Date.now()})} +function Qb(a,b){try{var c=T(a,{u:!b});a=c.path}catch(e){}var d={N:!1,exists:!1,error:0,name:null,path:null,object:null,Fa:!1,Ha:null,Ga:null};try{c=T(a,{parent:!0}),d.Fa=!0,d.Ha=c.path,d.Ga=c.node,d.name=N(a),c=T(a,{u:!b}),d.exists=!0,d.path=c.path,d.object=c.node,d.name=c.node.name,d.N="/"===c.path}catch(e){d.error=e.l}return d}function Rb(a,b,c,d){a="string"==typeof a?a:Ab(a);b=bb(a+"/"+b);return O.create(b,ub(c,d))} +function Sb(a){if(!(a.Aa||a.Ba||a.link||a.j)){if("undefined"!=typeof XMLHttpRequest)throw Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");try{a.j=la(a.url),a.o=a.j.length}catch(b){throw new O.g(29);}}} +var O={root:null,O:[],ea:{},streams:[],Y:1,C:null,da:"/",T:!1,ia:!0,va:null,R:0,na:{},g:class extends Error{name="ErrnoError";constructor(a){super(Ja?M(Tb(a)):"");this.l=a;for(var b in vb)if(vb[b]===a){this.code=b;break}}},ra:class{F={};node=null;get object(){return this.node}set object(a){this.node=a}get flags(){return this.F.flags}set flags(a){this.F.flags=a}get position(){return this.F.position}set position(a){this.F.position=a}},qa:class{h={};i={};A=null;constructor(a,b,c,d){a||=this;this.parent= +a;this.m=a.m;this.id=O.Y++;this.name=b;this.mode=c;this.rdev=d;this.atime=this.mtime=this.ctime=Date.now()}get read(){return 365===(this.mode&365)}set read(a){a?this.mode|=365:this.mode&=-366}get write(){return 146===(this.mode&146)}set write(a){a?this.mode|=146:this.mode&=-147}get Ba(){return Q(this.mode)}get Aa(){return 8192===(this.mode&61440)}},createNode(a,b,c,d){m("object"==typeof a);a=new O.qa(a,b,c,d);Db(a);return a},N(a){return a===a.parent},isFile(a){return 32768===(a&61440)},isFIFO(a){return 4096=== +(a&61440)},isSocket(a){return 49152===(a&49152)},aa:4096,ga:a=>O.streams[a],ta:{open(a){a.i=O.wa(a.node.rdev).i;a.i.open?.(a)},s(){throw new O.g(70);}},X:a=>a>>8,hb:a=>a&255,K:(a,b)=>a<<8|b,wa:a=>O.ea[a],pa(a,b){function c(h){m(0=e.length&&c(null)}"function"==typeof a&&(b=a,a=!1);O.R++;1 +{if(!h.type.pa)return d(null);h.type.pa(h,a,d)})},m(a,b,c){if("string"==typeof a)throw a;var d="/"===c,e=!c;if(d&&O.root)throw new O.g(10);if(!d&&!e){var g=T(c,{S:!1});c=g.path;g=g.node;if(g.A)throw new O.g(10);if(!Q(g.mode))throw new O.g(54);}b={type:a,Ea:b,ma:c,O:[]};a=a.m(b);a.m=b;b.root=a;d?O.root=a:g&&(g.A=b,g.m&&g.m.O.push(b));return a},qb(a){a=T(a,{S:!1});if(!a.node.A)throw new O.g(28);a=a.node;var b=a.A,c=Lb(b);Object.keys(O.C).forEach(d=>{for(d=O.C[d];d;){var e=d.L;c.includes(d.m)&&tb(d); +d=e}});a.A=null;b=a.m.O.indexOf(b);m(-1!==b);a.m.O.splice(b,1)},lookup(a,b){return a.h.lookup(a,b)},G(a,b,c){var d=T(a,{parent:!0}).node;a=N(a);if(!a)throw new O.g(28);if("."===a||".."===a)throw new O.g(20);var e=Fb(d,a);if(e)throw new O.g(e);if(!d.h.G)throw new O.g(63);return d.h.G(d,a,b,c)},oa(a){return Mb(T(a,{u:!0}).node)},ob(a){return Mb(a.node)},create(a,b=438){return O.G(a,b&4095|32768,0)},mkdir(a,b=511){return O.G(a,b&1023|16384,0)},ib(a,b){var c=a.split("/"),d="",e;for(e of c)if(e){if(d|| +"/"===a.charAt(0))d+="/";d+=e;try{O.mkdir(d,b)}catch(g){if(20!=g.l)throw g;}}},symlink(a,b){if(!gb(a))throw new O.g(44);var c=T(b,{parent:!0}).node;if(!c)throw new O.g(44);b=N(b);var d=Fb(c,b);if(d)throw new O.g(d);if(!c.h.symlink)throw new O.g(63);return c.h.symlink(c,b,a)},rename(a,b){var c=cb(a),d=cb(b),e=N(a),g=N(b);var h=T(a,{parent:!0});var l=h.node;h=T(b,{parent:!0});h=h.node;if(!l||!h)throw new O.g(44);if(l.m!==h.m)throw new O.g(75);var r=R(l,e);a=hb(a,d);if("."!==a.charAt(0))throw new O.g(28); +a=hb(b,c);if("."!==a.charAt(0))throw new O.g(55);try{var q=R(h,g)}catch(u){}if(r!==q){b=Q(r.mode);if(e=Gb(l,e,b))throw new O.g(e);if(e=q?Gb(h,g,b):Fb(h,g))throw new O.g(e);if(!l.h.rename)throw new O.g(63);if(r.A||q&&q.A)throw new O.g(10);if(h!==l&&(e=S(l,"w")))throw new O.g(e);tb(r);try{l.h.rename(r,h,g),r.parent=h}catch(u){throw u;}finally{Db(r)}}},rmdir(a){var b=T(a,{parent:!0}).node;a=N(a);var c=R(b,a),d=Gb(b,a,!0);if(d)throw new O.g(d);if(!b.h.rmdir)throw new O.g(63);if(c.A)throw new O.g(10); +b.h.rmdir(b,a);tb(c)},readdir(a){a=T(a,{u:!0}).node;return Hb(a.h.readdir,54)(a)},unlink(a){var b=T(a,{parent:!0}).node;if(!b)throw new O.g(44);a=N(a);var c=R(b,a),d=Gb(b,a,!1);if(d)throw new O.g(d);if(!b.h.unlink)throw new O.g(63);if(c.A)throw new O.g(10);b.h.unlink(b,a);tb(c)},readlink(a){a=T(a).node;if(!a)throw new O.g(44);if(!a.h.readlink)throw new O.g(28);return a.h.readlink(a)},stat(a,b){a=T(a,{u:!b}).node;return Hb(a.h.v,63)(a)},fstat(a){var b=U(a);a=b.node;var c=b.i.v;b=c?b:a;c??=a.h.v;Hb(c, +63);return c(b)},lstat(a){return O.stat(a,!0)},chmod(a,b,c){a="string"==typeof a?T(a,{u:!c}).node:a;Ob(null,a,b,c)},lchmod(a,b){O.chmod(a,b,!0)},fchmod(a,b){a=U(a);Ob(a,a.node,b,!1)},chown(a,b,c,d){a="string"==typeof a?T(a,{u:!d}).node:a;Kb(null,a,{timestamp:Date.now(),fa:d})},lchown(a,b,c){O.chown(a,b,c,!0)},fchown(a){a=U(a);Kb(a,a.node,{timestamp:Date.now(),fa:!1})},truncate(a,b){if(0>b)throw new O.g(28);a="string"==typeof a?T(a,{u:!0}).node:a;Pb(null,a,b)},eb(a,b){a=U(a);if(0>b||0===(a.flags&2097155))throw new O.g(28); +Pb(a,a.node,b)},rb(a,b,c){a=T(a,{u:!0}).node;Hb(a.h.B,63)(a,{atime:b,mtime:c})},open(a,b,c=438){if(""===a)throw new O.g(44);if("string"==typeof b){var d={r:0,"r+":2,w:577,"w+":578,a:1089,"a+":1090}[b];if("undefined"==typeof d)throw Error(`Unknown file open mode: ${b}`);b=d}c=b&64?c&4095|32768:0;if("object"==typeof a)d=a;else{var e=a.endsWith("/");a=T(a,{u:!(b&131072),Ca:!0});d=a.node;a=a.path}var g=!1;if(b&64)if(d){if(b&128)throw new O.g(20);}else{if(e)throw new O.g(31);d=O.G(a,c|511,0);g=!0}if(!d)throw new O.g(44); +8192===(d.mode&61440)&&(b&=-513);if(b&65536&&!Q(d.mode))throw new O.g(54);if(!g&&(e=d?40960===(d.mode&61440)?32:Q(d.mode)&&("r"!==Eb(b)||b&576)?31:S(d,Eb(b)):44))throw new O.g(e);b&512&&!g&&O.truncate(d,0);b&=-131713;e=Ib({node:d,path:Ab(d),flags:b,seekable:!0,position:0,i:d.i,Ja:[],error:!1});e.i.open&&e.i.open(e);g&&O.chmod(d,c&511);!f.logReadFiles||b&1||a in O.na||(O.na[a]=1);return e},close(a){if(null===a.fd)throw new O.g(8);a.J&&(a.J=null);try{a.i.close&&a.i.close(a)}catch(b){throw b;}finally{O.streams[a.fd]= +null}a.fd=null},s(a,b,c){if(null===a.fd)throw new O.g(8);if(!a.seekable||!a.i.s)throw new O.g(70);if(0!=c&&1!=c&&2!=c)throw new O.g(28);a.position=a.i.s(a,b,c);a.Ja=[];return a.position},read(a,b,c,d,e){m(0<=c);if(0>d||0>e)throw new O.g(28);if(null===a.fd)throw new O.g(8);if(1===(a.flags&2097155))throw new O.g(8);if(Q(a.node.mode))throw new O.g(31);if(!a.i.read)throw new O.g(28);var g="undefined"!=typeof e;if(!g)e=a.position;else if(!a.seekable)throw new O.g(70);b=a.i.read(a,b,c,d,e);g||(a.position+= +b);return b},write(a,b,c,d,e,g){m(0<=c);if(0>d||0>e)throw new O.g(28);if(null===a.fd)throw new O.g(8);if(0===(a.flags&2097155))throw new O.g(8);if(Q(a.node.mode))throw new O.g(31);if(!a.i.write)throw new O.g(28);a.seekable&&a.flags&1024&&O.s(a,0,2);var h="undefined"!=typeof e;if(!h)e=a.position;else if(!a.seekable)throw new O.g(70);b=a.i.write(a,b,c,d,e,g);h||(a.position+=b);return b},M(a,b,c,d,e){if(0!==(d&2)&&0===(e&2)&&2!==(a.flags&2097155))throw new O.g(2);if(1===(a.flags&2097155))throw new O.g(2); +if(!a.i.M)throw new O.g(43);if(!b)throw new O.g(28);return a.i.M(a,b,c,d,e)},P(a,b,c,d,e){m(0<=c);return a.i.P?a.i.P(a,b,c,d,e):0},W(a,b,c){if(!a.i.W)throw new O.g(59);return a.i.W(a,b,c)},readFile(a,b={}){b.flags=b.flags||0;b.encoding=b.encoding||"binary";if("utf8"!==b.encoding&&"binary"!==b.encoding)throw Error(`Invalid encoding type "${b.encoding}"`);var c=O.open(a,b.flags);a=O.stat(a).size;var d=new Uint8Array(a);O.read(c,d,0,a,0);"utf8"===b.encoding&&(d=$a(d));O.close(c);return d},writeFile(a, +b,c={}){c.flags=c.flags||577;a=O.open(a,c.flags,c.mode);"string"==typeof b&&(b=new Uint8Array(lb(b)));if(ArrayBuffer.isView(b))O.write(a,b,0,b.byteLength,void 0,c.Ta);else throw Error("Unsupported data type");O.close(a)},cwd:()=>O.da,chdir(a){a=T(a,{u:!0});if(null===a.node)throw new O.g(44);if(!Q(a.node.mode))throw new O.g(54);var b=S(a.node,"x");if(b)throw new O.g(b);O.da=a.path},mb(){O.T=!1;Ub(0);for(var a of O.streams)a&&O.close(a)},ab(a,b){a=Qb(a,b);return a.exists?a.object:null},Xa(a,b){a="string"== +typeof a?a:Ab(a);for(b=b.split("/").reverse();b.length;){var c=b.pop();if(c){var d=bb(a+"/"+c);try{O.mkdir(d)}catch(e){if(20!=e.l)throw e;}a=d}}return d},I(a,b,c,d){a=db("string"==typeof a?a:Ab(a),b);b=ub(!!c,!!d);var e;(e=O.I).X??(e.X=64);e=O.K(O.I.X++,0);ob(e,{open(g){g.seekable=!1},close(){d?.buffer?.length&&d(10)},read(g,h,l,r){for(var q=0,u=0;u=n.length)return 0;G=Math.min(n.length-D,G);m(0<=G);if(n.slice)for(var H=0;Hthis.length-1||0>n)){var w=n%this.chunkSize;return this.U(n/this.chunkSize|0)[w]}}Da(n){this.U= +n}la(){var n=new XMLHttpRequest;n.open("HEAD",c,!1);n.send(null);if(!(200<=n.status&&300>n.status||304===n.status))throw Error("Couldn't load "+c+". Status: "+n.status);var w=Number(n.getResponseHeader("Content-length")),F,G=(F=n.getResponseHeader("Accept-Ranges"))&&"bytes"===F;n=(F=n.getResponseHeader("Content-Encoding"))&&"gzip"===F;var D=1048576;G||(D=w);var H=this;H.Da(fa=>{var za=fa*D,ha=(fa+1)*D-1;ha=Math.min(ha,w-1);if("undefined"==typeof H.F[fa]){var Bc=H.F;if(za>ha)throw Error("invalid range ("+ +za+", "+ha+") or no bytes requested!");if(ha>w-1)throw Error("only "+w+" bytes available! programmer error!");var J=new XMLHttpRequest;J.open("GET",c,!1);w!==D&&J.setRequestHeader("Range","bytes="+za+"-"+ha);J.responseType="arraybuffer";J.overrideMimeType&&J.overrideMimeType("text/plain; charset=x-user-defined");J.send(null);if(!(200<=J.status&&300>J.status||304===J.status))throw Error("Couldn't load "+c+". Status: "+J.status);za=void 0!==J.response?new Uint8Array(J.response||[]):lb(J.responseText|| +"");Bc[fa]=za}if("undefined"==typeof H.F[fa])throw Error("doXHR failed!");return H.F[fa]});if(n||!w)D=w=1,D=w=this.U(0).length,p("LazyFiles on gzip forces download of the whole file when length is accessed");this.ka=w;this.ja=D;this.V=!0}get length(){this.V||this.la();return this.ka}get chunkSize(){this.V||this.la();return this.ja}}if("undefined"!=typeof XMLHttpRequest){if(!ba)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc"; +var l=new h;var r=void 0}else r=c,l=void 0;var q=Rb(a,b,d,e);l?q.j=l:r&&(q.j=null,q.url=r);Object.defineProperties(q,{o:{get:function(){return this.j.length}}});var u={};Object.keys(q.i).forEach(n=>{var w=q.i[n];u[n]=(...F)=>{Sb(q);return w(...F)}});u.read=(n,w,F,G,D)=>{Sb(q);return g(n,w,F,G,D)};u.M=(n,w,F)=>{Sb(q);var G=sb();if(!G)throw new O.g(48);g(n,A,G,w,F);return{Ia:G,sa:!0}};q.i=u;return q},Ka(){v("FS.absolutePath has been removed; use PATH_FS.resolve instead")},Ua(){v("FS.createFolder has been removed; use FS.mkdir instead")}, +Wa(){v("FS.createLink has been removed; use FS.symlink instead")},gb(){v("FS.joinPath has been removed; use PATH.join instead")},jb(){v("FS.mmapAlloc has been replaced by the top level function mmapAlloc")},nb(){v("FS.standardizePath has been removed; use PATH.normalize instead")}};function Vb(a,b,c){if("/"===b.charAt(0))return b;a=-100===a?O.cwd():U(a).path;if(0==b.length){if(!c)throw new O.g(44);return a}return a+"/"+b} +function Wb(a,b){x[a>>2]=b.dev;x[a+4>>2]=b.mode;x[a+8>>2]=b.nlink;x[a+12>>2]=b.uid;x[a+16>>2]=b.gid;x[a+20>>2]=b.rdev;C[a+24>>3]=BigInt(b.size);B[a+32>>2]=4096;B[a+36>>2]=b.blocks;var c=b.atime.getTime(),d=b.mtime.getTime(),e=b.ctime.getTime();C[a+40>>3]=BigInt(Math.floor(c/1E3));x[a+48>>2]=c%1E3*1E6;C[a+56>>3]=BigInt(Math.floor(d/1E3));x[a+64>>2]=d%1E3*1E6;C[a+72>>3]=BigInt(Math.floor(e/1E3));x[a+80>>2]=e%1E3*1E6;C[a+88>>3]=BigInt(b.ino);return 0} +var Xb=void 0,V=()=>{m(void 0!=Xb);var a=B[+Xb>>2];Xb+=4;return a},W=(a,b,c)=>{m("number"==typeof c,"stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return kb(a,Ha,b,c)},Yb=0,Zb=a=>0===a%4&&(0!==a%100||0===a%400),$b=[0,31,60,91,121,152,182,213,244,274,305,335],ac=[0,31,59,90,120,151,181,212,243,273,304,334],bc={},cc=a=>{if(a instanceof Ta||"unwind"==a)return ra;ua();a instanceof WebAssembly.RuntimeError&&0>=X()&&t("Stack overflow detected. You can try increasing -sSTACK_SIZE (currently set to 65536)"); +ea(1,a)},dc=a=>{ra=a;Ya||0{ra=a;ec();(Ya||0{if(qa)t("user callback triggered after runtime exited or application aborted. Ignoring."); +else try{if(a(),!(Ya||0{if(!ic){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"==typeof navigator&&navigator.language||"C").replace("-","_")+".UTF-8",_:da||"./this.program"},b;for(b in hc)void 0===hc[b]?delete a[b]:a[b]=hc[b];var c=[];for(b in a)c.push(`${b}=${a[b]}`);ic=c}return ic},ic,kc=(a,b,c,d)=>{for(var e=0,g=0;g>2],l=x[b+4>>2];b+=8;h=O.read(a,A,h,l,d);if(0>h)return-1; +e+=h;if(h{for(var e=0,g=0;g>2],l=x[b+4>>2];b+=8;h=O.write(a,A,h,l,d);if(0>h)return-1;e+=h;if(h{Bb(a,b,c,d,e,l,r,q).then(g).catch(h)};O.lb=Bb;O.C=Array(4096);O.m(P,{},"/");O.mkdir("/tmp");O.mkdir("/home");O.mkdir("/home/web_user"); +(function(){O.mkdir("/dev");ob(O.K(1,3),{read:()=>0,write:(d,e,g,h)=>h,s:()=>0});Nb("/dev/null",O.K(1,3));nb(O.K(5,0),qb);nb(O.K(6,0),rb);Nb("/dev/tty",O.K(5,0));Nb("/dev/tty1",O.K(6,0));var a=new Uint8Array(1024),b=0,c=()=>{0===b&&(fb(a),b=a.byteLength);return a[--b]};O.I("/dev","random",c);O.I("/dev","urandom",c);O.mkdir("/dev/shm");O.mkdir("/dev/shm/tmp")})(); +(function(){O.mkdir("/proc");var a=O.mkdir("/proc/self");O.mkdir("/proc/self/fd");O.m({m(){var b=O.createNode(a,"fd",16895,73);b.i={s:P.i.s};b.h={lookup(c,d){c=+d;var e=U(c);c={parent:null,m:{ma:"fake"},h:{readlink:()=>e.path},id:c+1};return c.parent=c},readdir(){return Array.from(O.streams.entries()).filter(([,c])=>c).map(([c])=>c.toString())}};return b}},{},"/proc/self/fd")})();O.va={MEMFS:P};f.noExitRuntime&&(Ya=f.noExitRuntime);f.preloadPlugins&&(xb=f.preloadPlugins);f.print&&(p=f.print); +f.printErr&&(t=f.printErr);f.wasmBinary&&(pa=f.wasmBinary);Object.getOwnPropertyDescriptor(f,"fetchSettings")&&v("`Module.fetchSettings` was supplied but `fetchSettings` not included in INCOMING_MODULE_JS_API");f.thisProgram&&(da=f.thisProgram);m("undefined"==typeof f.memoryInitializerPrefixURL,"Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");m("undefined"==typeof f.pthreadMainPrefixURL,"Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead"); +m("undefined"==typeof f.cdInitializerPrefixURL,"Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");m("undefined"==typeof f.filePackagePrefixURL,"Module.filePackagePrefixURL option was removed, use Module.locateFile instead");m("undefined"==typeof f.read,"Module.read option was removed");m("undefined"==typeof f.readAsync,"Module.readAsync option was removed (modify readAsync in JS)");m("undefined"==typeof f.readBinary,"Module.readBinary option was removed (modify readBinary in JS)"); +m("undefined"==typeof f.setWindowTitle,"Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)");m("undefined"==typeof f.TOTAL_MEMORY,"Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");m("undefined"==typeof f.ENVIRONMENT,"Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)");m("undefined"==typeof f.STACK_SIZE,"STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time"); +m("undefined"==typeof f.wasmMemory,"Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally");m("undefined"==typeof f.INITIAL_MEMORY,"Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically");f.callMain=nc;f.FS=O; +"writeI53ToI64 writeI53ToI64Clamped writeI53ToI64Signaling writeI53ToU64Clamped writeI53ToU64Signaling readI53FromI64 readI53FromU64 convertI32PairToI53 convertI32PairToI53Checked convertU32PairToI53 getTempRet0 setTempRet0 zeroMemory withStackSave inetPton4 inetNtop4 inetPton6 inetNtop6 readSockaddr writeSockaddr readEmAsmArgs jstoi_q autoResumeAudioContext dynCallLegacy getDynCaller dynCall runtimeKeepalivePush runtimeKeepalivePop asmjsMangle HandleAllocator getNativeTypeSize addOnInit addOnPostCtor addOnPreMain addOnExit STACK_SIZE STACK_ALIGN POINTER_SIZE ASSERTIONS ccall cwrap convertJsFunctionToWasm getEmptyTableSlot updateTableMap getFunctionAddress addFunction removeFunction intArrayToString AsciiToString stringToAscii UTF16ToString stringToUTF16 lengthBytesUTF16 UTF32ToString stringToUTF32 lengthBytesUTF32 stringToNewUTF8 writeArrayToMemory registerKeyEventCallback maybeCStringToJsString findEventTarget getBoundingClientRect fillMouseEventData registerMouseEventCallback registerWheelEventCallback registerUiEventCallback registerFocusEventCallback fillDeviceOrientationEventData registerDeviceOrientationEventCallback fillDeviceMotionEventData registerDeviceMotionEventCallback screenOrientation fillOrientationChangeEventData registerOrientationChangeEventCallback fillFullscreenChangeEventData registerFullscreenChangeEventCallback JSEvents_requestFullscreen JSEvents_resizeCanvasForFullscreen registerRestoreOldStyle hideEverythingExceptGivenElement restoreHiddenElements setLetterbox softFullscreenResizeWebGLRenderTarget doRequestFullscreen fillPointerlockChangeEventData registerPointerlockChangeEventCallback registerPointerlockErrorEventCallback requestPointerLock fillVisibilityChangeEventData registerVisibilityChangeEventCallback registerTouchEventCallback fillGamepadEventData registerGamepadEventCallback registerBeforeUnloadEventCallback fillBatteryEventData registerBatteryEventCallback setCanvasElementSize getCanvasElementSize jsStackTrace getCallstack convertPCtoSourceLocation wasiRightsToMuslOFlags wasiOFlagsToMuslOFlags safeSetTimeout setImmediateWrapped safeRequestAnimationFrame clearImmediateWrapped registerPostMainLoop registerPreMainLoop getPromise makePromise idsToPromises makePromiseCallback ExceptionInfo findMatchingCatch Browser_asyncPrepareDataCounter arraySum addDays getSocketFromFD getSocketAddress FS_mkdirTree _setNetworkCallback heapObjectForWebGLType toTypedArrayIndex webgl_enable_ANGLE_instanced_arrays webgl_enable_OES_vertex_array_object webgl_enable_WEBGL_draw_buffers webgl_enable_WEBGL_multi_draw webgl_enable_EXT_polygon_offset_clamp webgl_enable_EXT_clip_control webgl_enable_WEBGL_polygon_mode emscriptenWebGLGet computeUnpackAlignedImageSize colorChannelsInGlTextureFormat emscriptenWebGLGetTexPixelData emscriptenWebGLGetUniform webglGetUniformLocation webglPrepareUniformLocationsBeforeFirstUse webglGetLeftBracePos emscriptenWebGLGetVertexAttrib __glGetActiveAttribOrUniform writeGLArray registerWebGlEventCallback runAndAbortIfError ALLOC_NORMAL ALLOC_STACK allocate writeStringToMemory writeAsciiToMemory demangle stackTrace".split(" ").forEach(function(a){Ba(a,()=> +{var b=`\`${a}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`,c=a;c.startsWith("_")||(c="$"+a);b+=` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${c}')`;Aa(a)&&(b+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you");z(b)});Da(a)});"run addRunDependency removeRunDependency out err abort wasmMemory wasmExports HEAPF32 HEAPF64 HEAP8 HEAPU8 HEAP16 HEAPU16 HEAP32 HEAPU32 HEAP64 HEAPU64 writeStackCookie checkStackCookie INT53_MAX INT53_MIN bigintToI53Checked stackSave stackRestore stackAlloc ptrToString exitJS getHeapMax growMemory ENV ERRNO_CODES strError DNS Protocols Sockets timers warnOnce readEmAsmArgsArray getExecutableName handleException keepRuntimeAlive callUserCallback maybeExit asyncLoad alignMemory mmapAlloc wasmTable getUniqueRunDependency noExitRuntime addOnPreRun addOnPostRun freeTableIndexes functionsInTableMap setValue getValue PATH PATH_FS UTF8Decoder UTF8ArrayToString UTF8ToString stringToUTF8Array stringToUTF8 lengthBytesUTF8 intArrayFromString UTF16Decoder stringToUTF8OnStack JSEvents specialHTMLTargets findCanvasEventTarget currentFullscreenStrategy restoreOldWindowedStyle UNWIND_CACHE ExitStatus getEnvStrings checkWasiClock doReadv doWritev initRandomFill randomFill emSetImmediate emClearImmediate_deps emClearImmediate promiseMap uncaughtExceptionCount exceptionLast exceptionCaught Browser requestFullscreen requestFullScreen setCanvasSize getUserMedia createContext getPreloadedImageData__data wget MONTH_DAYS_REGULAR MONTH_DAYS_LEAP MONTH_DAYS_REGULAR_CUMULATIVE MONTH_DAYS_LEAP_CUMULATIVE isLeapYear ydayFromDate SYSCALLS preloadPlugins FS_createPreloadedFile FS_preloadFile FS_modeStringToFlags FS_getMode FS_stdin_getChar_buffer FS_stdin_getChar FS_unlink FS_createPath FS_createDevice FS_readFile FS_root FS_mounts FS_devices FS_streams FS_nextInode FS_nameTable FS_currentPath FS_initialized FS_ignorePermissions FS_filesystems FS_syncFSRequests FS_readFiles FS_lookupPath FS_getPath FS_hashName FS_hashAddNode FS_hashRemoveNode FS_lookupNode FS_createNode FS_destroyNode FS_isRoot FS_isMountpoint FS_isFile FS_isDir FS_isLink FS_isChrdev FS_isBlkdev FS_isFIFO FS_isSocket FS_flagsToPermissionString FS_nodePermissions FS_mayLookup FS_mayCreate FS_mayDelete FS_mayOpen FS_checkOpExists FS_nextfd FS_getStreamChecked FS_getStream FS_createStream FS_closeStream FS_dupStream FS_doSetAttr FS_chrdev_stream_ops FS_major FS_minor FS_makedev FS_registerDevice FS_getDevice FS_getMounts FS_syncfs FS_mount FS_unmount FS_lookup FS_mknod FS_statfs FS_statfsStream FS_statfsNode FS_create FS_mkdir FS_mkdev FS_symlink FS_rename FS_rmdir FS_readdir FS_readlink FS_stat FS_fstat FS_lstat FS_doChmod FS_chmod FS_lchmod FS_fchmod FS_doChown FS_chown FS_lchown FS_fchown FS_doTruncate FS_truncate FS_ftruncate FS_utime FS_open FS_close FS_isClosed FS_llseek FS_read FS_write FS_mmap FS_msync FS_ioctl FS_writeFile FS_cwd FS_chdir FS_createDefaultDirectories FS_createDefaultDevices FS_createSpecialDirectories FS_createStandardStreams FS_staticInit FS_init FS_quit FS_findObject FS_analyzePath FS_createFile FS_createDataFile FS_forceLoadFile FS_createLazyFile FS_absolutePath FS_createFolder FS_createLink FS_joinPath FS_mmapAlloc FS_standardizePath MEMFS TTY PIPEFS SOCKFS tempFixedLengthArray miniTempWebGLFloatBuffers miniTempWebGLIntBuffers GL AL GLUT EGL GLEW IDBStore SDL SDL_gfx allocateUTF8 allocateUTF8OnStack print printErr jstoi_s".split(" ").forEach(Da); +var oc=f._main=y("_main"),Tb=y("_strerror"),Ub=y("_fflush"),ta=y("_emscripten_stack_get_end"),pc=y("__emscripten_timeout"),Y=y("_setThrew"),qc=y("_emscripten_stack_init"),Z=y("__emscripten_stack_restore"),rc=y("__emscripten_stack_alloc"),X=y("_emscripten_stack_get_current"),dynCall_v=y("dynCall_v"),dynCall_iii=y("dynCall_iii"),sc=y("dynCall_viii"),tc=y("dynCall_iiii"),uc=y("dynCall_ii"),dynCall_vi=y("dynCall_vi"),vc=y("dynCall_iiiii"),wc=y("dynCall_iiiiiiiii"),dynCall_vii=y("dynCall_vii"),xc=y("dynCall_iiji"), +yc=y("dynCall_viiii"),zc=y("dynCall_viiiii"),Ac=y("dynCall_viiiiii"),Oc={__assert_fail:(a,b,c,d)=>v(`Assertion failed: ${M(a)}, at: `+[b?M(b):"unknown filename",c,d?M(d):"unknown function"]),__syscall_dup:function(a){try{var b=U(a);return Jb(b).fd}catch(c){if("undefined"==typeof O||"ErrnoError"!==c.name)throw c;return-c.l}},__syscall_dup3:function(a,b,c){try{var d=U(a);m(!c);if(d.fd===b)return-28;if(0>b||b>=O.aa)return-8;var e=O.ga(b);e&&O.close(e);return Jb(d,b).fd}catch(g){if("undefined"==typeof O|| +"ErrnoError"!==g.name)throw g;return-g.l}},__syscall_fcntl64:function(a,b,c){Xb=c;try{var d=U(a);switch(b){case 0:var e=V();if(0>e)break;for(;O.streams[e];)e++;return Jb(d,e).fd;case 1:case 2:return 0;case 3:return d.flags;case 4:return e=V(),d.flags|=e,0;case 12:return e=V(),Ia[e+0>>1]=2,0;case 13:case 14:return 0}return-28}catch(g){if("undefined"==typeof O||"ErrnoError"!==g.name)throw g;return-g.l}},__syscall_fstat64:function(a,b){try{return Wb(b,O.fstat(a))}catch(c){if("undefined"==typeof O||"ErrnoError"!== +c.name)throw c;return-c.l}},__syscall_getdents64:function(a,b,c){try{var d=U(a);d.J||(d.J=O.readdir(d.path));a=0;var e=O.s(d,0,1),g=Math.floor(e/280),h=Math.min(d.J.length,g+Math.floor(c/280));for(c=g;c>3]=BigInt(r);C[b+a+8>>3]=BigInt(280*(c+ +1));Ia[b+a+16>>1]=280;A[b+a+18]=q;W(l,b+a+19,256);a+=280}O.s(d,280*c,0);return a}catch(n){if("undefined"==typeof O||"ErrnoError"!==n.name)throw n;return-n.l}},__syscall_ioctl:function(a,b,c){Xb=c;try{var d=U(a);switch(b){case 21509:return d.tty?0:-59;case 21505:if(!d.tty)return-59;if(d.tty.H.xa){a=[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];var e=V();B[e>>2]=25856;B[e+4>>2]=5;B[e+8>>2]=191;B[e+12>>2]=35387;for(var g=0;32>g;g++)A[e+g+17]=a[g]||0}return 0;case 21510:case 21511:case 21512:return d.tty? +0:-59;case 21506:case 21507:case 21508:if(!d.tty)return-59;if(d.tty.H.ya)for(e=V(),a=[],g=0;32>g;g++)a.push(A[e+g+17]);return 0;case 21519:if(!d.tty)return-59;e=V();return B[e>>2]=0;case 21520:return d.tty?-28:-59;case 21537:case 21531:return e=V(),O.W(d,b,e);case 21523:if(!d.tty)return-59;d.tty.H.za&&(g=[24,80],e=V(),Ia[e>>1]=g[0],Ia[e+2>>1]=g[1]);return 0;case 21524:return d.tty?0:-59;case 21515:return d.tty?0:-59;default:return-28}}catch(h){if("undefined"==typeof O||"ErrnoError"!==h.name)throw h; +return-h.l}},__syscall_lstat64:function(a,b){try{return a=M(a),Wb(b,O.lstat(a))}catch(c){if("undefined"==typeof O||"ErrnoError"!==c.name)throw c;return-c.l}},__syscall_newfstatat:function(a,b,c,d){try{b=M(b);var e=d&256,g=d&4096;d&=-6401;m(!d,`unknown flags in __syscall_newfstatat: ${d}`);b=Vb(a,b,g);return Wb(c,e?O.lstat(b):O.stat(b))}catch(h){if("undefined"==typeof O||"ErrnoError"!==h.name)throw h;return-h.l}},__syscall_openat:function(a,b,c,d){Xb=d;try{b=M(b);b=Vb(a,b);var e=d?V():0;return O.open(b, +c,e).fd}catch(g){if("undefined"==typeof O||"ErrnoError"!==g.name)throw g;return-g.l}},__syscall_renameat:function(a,b,c,d){try{return b=M(b),d=M(d),b=Vb(a,b),d=Vb(c,d),O.rename(b,d),0}catch(e){if("undefined"==typeof O||"ErrnoError"!==e.name)throw e;return-e.l}},__syscall_rmdir:function(a){try{return a=M(a),O.rmdir(a),0}catch(b){if("undefined"==typeof O||"ErrnoError"!==b.name)throw b;return-b.l}},__syscall_stat64:function(a,b){try{return a=M(a),Wb(b,O.stat(a))}catch(c){if("undefined"==typeof O||"ErrnoError"!== +c.name)throw c;return-c.l}},__syscall_unlinkat:function(a,b,c){try{b=M(b);b=Vb(a,b);if(c)if(512===c)O.rmdir(b);else return-28;else O.unlink(b);return 0}catch(d){if("undefined"==typeof O||"ErrnoError"!==d.name)throw d;return-d.l}},_abort_js:()=>v("native code called abort()"),_emscripten_runtime_keepalive_clear:()=>{Ya=!1;Yb=0},_emscripten_throw_longjmp:()=>{throw Infinity;},_gmtime_js:function(a,b){a=-9007199254740992>a||9007199254740992>2]=a.getUTCSeconds(); +B[b+4>>2]=a.getUTCMinutes();B[b+8>>2]=a.getUTCHours();B[b+12>>2]=a.getUTCDate();B[b+16>>2]=a.getUTCMonth();B[b+20>>2]=a.getUTCFullYear()-1900;B[b+24>>2]=a.getUTCDay();B[b+28>>2]=(a.getTime()-Date.UTC(a.getUTCFullYear(),0,1,0,0,0,0))/864E5|0},_localtime_js:function(a,b){a=-9007199254740992>a||9007199254740992>2]=a.getSeconds();B[b+4>>2]=a.getMinutes();B[b+8>>2]=a.getHours();B[b+12>>2]=a.getDate();B[b+16>>2]=a.getMonth();B[b+20>>2]=a.getFullYear()-1900;B[b+24>> +2]=a.getDay();B[b+28>>2]=(Zb(a.getFullYear())?$b:ac)[a.getMonth()]+a.getDate()-1|0;B[b+36>>2]=-(60*a.getTimezoneOffset());var c=(new Date(a.getFullYear(),6,1)).getTimezoneOffset(),d=(new Date(a.getFullYear(),0,1)).getTimezoneOffset();B[b+32>>2]=(c!=d&&a.getTimezoneOffset()==Math.min(d,c))|0},_mktime_js:function(a){var b=new Date(B[a+20>>2]+1900,B[a+16>>2],B[a+12>>2],B[a+8>>2],B[a+4>>2],B[a>>2],0),c=B[a+32>>2],d=b.getTimezoneOffset(),e=(new Date(b.getFullYear(),6,1)).getTimezoneOffset(),g=(new Date(b.getFullYear(), +0,1)).getTimezoneOffset(),h=Math.min(g,e);0>c?B[a+32>>2]=Number(e!=g&&h==d):0>2]=b.getDay();B[a+28>>2]=(Zb(b.getFullYear())?$b:ac)[b.getMonth()]+b.getDate()-1|0;B[a>>2]=b.getSeconds();B[a+4>>2]=b.getMinutes();B[a+8>>2]=b.getHours();B[a+12>>2]=b.getDate();B[a+16>>2]=b.getMonth();B[a+20>>2]=b.getYear();a=b.getTime();return BigInt(isNaN(a)?-1:a/1E3)},_setitimer_js:(a,b)=>{bc[a]&&(clearTimeout(bc[a].id),delete bc[a]);if(!b)return 0; +var c=setTimeout(()=>{m(a in bc);delete bc[a];gc(()=>pc(a,performance.now()))},b);bc[a]={id:c,pb:b};return 0},_tzset_js:(a,b,c,d)=>{var e=(new Date).getFullYear(),g=(new Date(e,0,1)).getTimezoneOffset();e=(new Date(e,6,1)).getTimezoneOffset();x[a>>2]=60*Math.max(g,e);B[b>>2]=Number(g!=e);b=h=>{var l=Math.abs(h);return`UTC${0<=h?"-":"+"}${String(Math.floor(l/60)).padStart(2,"0")}${String(l%60).padStart(2,"0")}`};a=b(g);b=b(e);m(a);m(b);m(16>=jb(a),`timezone name truncated to fit in TZNAME_MAX (${a})`); +m(16>=jb(b),`timezone name truncated to fit in TZNAME_MAX (${b})`);e=a))return 28;C[c>>3]=BigInt(Math.round(1E6*(0===a?Date.now():performance.now())));return 0},emscripten_date_now:()=>Date.now(),emscripten_resize_heap:a=>{var b=Ha.length;a>>>=0;m(a>b);if(2147483648=c;c*=2){var d=b*(1+.2/c);d= +Math.min(d,a+100663296);var e=Math,g=e.min;d=Math.max(a,d);m(65536,"alignment argument is required");e=g.call(e,2147483648,65536*Math.ceil(d/65536));a:{g=e;d=Ga.buffer.byteLength;try{Ga.grow((g-d+65535)/65536|0);Ka();var h=1;break a}catch(l){t(`growMemory: Attempted to grow heap from ${d} bytes to ${g} bytes, but got error: ${l}`)}h=void 0}if(h)return!0}t(`Failed to grow the heap from ${b} bytes to ${e} bytes, not enough memory!`);return!1},environ_get:(a,b)=>{var c=0,d=0,e;for(e of jc()){var g=b+ +c;x[a+d>>2]=g;c+=W(e,g,Infinity)+1;d+=4}return 0},environ_sizes_get:(a,b)=>{var c=jc();x[a>>2]=c.length;a=0;for(var d of c)a+=jb(d)+1;x[b>>2]=a;return 0},exit:fc,fd_close:function(a){try{var b=U(a);O.close(b);return 0}catch(c){if("undefined"==typeof O||"ErrnoError"!==c.name)throw c;return c.l}},fd_pread:function(a,b,c,d,e){d=-9007199254740992>d||9007199254740992>2]=h;return 0}catch(l){if("undefined"==typeof O||"ErrnoError"!== +l.name)throw l;return l.l}},fd_pwrite:function(a,b,c,d,e){d=-9007199254740992>d||9007199254740992>2]=h;return 0}catch(l){if("undefined"==typeof O||"ErrnoError"!==l.name)throw l;return l.l}},fd_read:function(a,b,c,d){try{var e=U(a),g=kc(e,b,c);x[d>>2]=g;return 0}catch(h){if("undefined"==typeof O||"ErrnoError"!==h.name)throw h;return h.l}},fd_seek:function(a,b,c,d){b=-9007199254740992>b||9007199254740992>3]=BigInt(e.position);e.J&&0===b&&0===c&&(e.J=null);return 0}catch(g){if("undefined"==typeof O||"ErrnoError"!==g.name)throw g;return g.l}},fd_write:function(a,b,c,d){try{var e=U(a),g=lc(e,b,c);x[d>>2]=g;return 0}catch(h){if("undefined"==typeof O||"ErrnoError"!==h.name)throw h;return h.l}},invoke_ii:Cc,invoke_iii:Dc,invoke_iiii:Ec,invoke_iiiii:Fc,invoke_iiiiiiiii:Gc,invoke_iiji:Hc,invoke_vi:Ic,invoke_vii:Jc,invoke_viii:Kc,invoke_viiii:Lc,invoke_viiiii:Mc,invoke_viiiiii:Nc, +proc_exit:dc},L=await (async function(){function a(d){L=d.exports;Ga=L.memory;m(Ga,"memory not found in wasm exports");Ka();mc=L.__indirect_function_table;m(mc,"table not found in wasm exports");d=L;f._main=oc=K("__main_argc_argv",2);Tb=K("strerror",1);Ub=K("fflush",1);ta=d.emscripten_stack_get_end;pc=K("_emscripten_timeout",2);Y=K("setThrew",2);qc=d.emscripten_stack_init;Z=d._emscripten_stack_restore;rc=d._emscripten_stack_alloc;X=d.emscripten_stack_get_current;dynCall_v=K("dynCall_v", +1);dynCall_iii=K("dynCall_iii",3);sc=K("dynCall_viii",4);tc=K("dynCall_iiii",4);uc=K("dynCall_ii",2);dynCall_vi=K("dynCall_vi",2);vc=K("dynCall_iiiii",5);wc=K("dynCall_iiiiiiiii",9);dynCall_vii=K("dynCall_vii",3);xc=K("dynCall_iiji",4);yc=K("dynCall_viiii",5);zc=K("dynCall_viiiii",6);Ac=K("dynCall_viiiiii",7);Oa("wasm-instantiate");return L}Na("wasm-instantiate");var b=f,c={env:Oc,wasi_snapshot_preview1:Oc};if(f.instantiateWasm)return new Promise((d,e)=>{try{f.instantiateWasm(c,(g,h)=>{d(a(g,h))})}catch(g){t(`Module.instantiateWasm callback failed with error: ${g}`), +e(g)}});Pa??=f.locateFile?f.locateFile?f.locateFile("gs.wasm",ja):ja+"gs.wasm":(new URL("gs.wasm",import.meta.url)).href;return function(d){m(f===b,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");b=null;return a(d.instance)}(await Sa(c))}());function Ic(a,b){var c=X();try{dynCall_vi(a,b)}catch(d){Z(c);if(d!==d+0)throw d;Y(1,0)}} +function Jc(a,b,c){var d=X();try{dynCall_vii(a,b,c)}catch(e){Z(d);if(e!==e+0)throw e;Y(1,0)}}function Cc(a,b){var c=X();try{return uc(a,b)}catch(d){Z(c);if(d!==d+0)throw d;Y(1,0)}}function Ec(a,b,c,d){var e=X();try{return tc(a,b,c,d)}catch(g){Z(e);if(g!==g+0)throw g;Y(1,0)}}function Dc(a,b,c){var d=X();try{return dynCall_iii(a,b,c)}catch(e){Z(d);if(e!==e+0)throw e;Y(1,0)}}function Kc(a,b,c,d){var e=X();try{sc(a,b,c,d)}catch(g){Z(e);if(g!==g+0)throw g;Y(1,0)}} +function Lc(a,b,c,d,e){var g=X();try{yc(a,b,c,d,e)}catch(h){Z(g);if(h!==h+0)throw h;Y(1,0)}}function Hc(a,b,c,d){var e=X();try{return xc(a,b,c,d)}catch(g){Z(e);if(g!==g+0)throw g;Y(1,0)}}function Fc(a,b,c,d,e){var g=X();try{return vc(a,b,c,d,e)}catch(h){Z(g);if(h!==h+0)throw h;Y(1,0)}}function Mc(a,b,c,d,e,g){var h=X();try{zc(a,b,c,d,e,g)}catch(l){Z(h);if(l!==l+0)throw l;Y(1,0)}}function Nc(a,b,c,d,e,g,h){var l=X();try{Ac(a,b,c,d,e,g,h)}catch(r){Z(l);if(r!==r+0)throw r;Y(1,0)}} +function Gc(a,b,c,d,e,g,h,l,r){var q=X();try{return wc(a,b,c,d,e,g,h,l,r)}catch(u){Z(q);if(u!==u+0)throw u;Y(1,0)}}var Pc; +function nc(a=[]){m(0==E,'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])');m("undefined"===typeof Wa||0==Wa.length,"cannot call main when preRun functions remain to be called");var b=oc;a.unshift(da);var c=a.length,d=rc(4*(c+1)),e=d;a.forEach(h=>{var l=x,r=e>>2,q=jb(h)+1,u=rc(q);W(h,u,q);l[r]=u;e+=4});x[e>>2]=0;try{var g=b(c,d);fc(g,!0);return g}catch(h){return cc(h)}} +function Qc(){function a(){m(!Pc);Pc=!0;f.calledRun=!0;if(!qa){m(!Ja);Ja=!0;ua();f.noFSInit||O.T||yb();L.__wasm_call_ctors();O.ia=!1;ua();Ea?.(f);f.onRuntimeInitialized?.();ya("onRuntimeInitialized");ua();if(f.postRun)for("function"==typeof f.postRun&&(f.postRun=[f.postRun]);f.postRun.length;){var b=f.postRun.shift();Va.push(b)}ya("postRun");Ua(Va)}}if(0{setTimeout(()=>f.setStatus(""),1);a()},1)):a(),ua())}}function ec(){var a=p,b=t,c=!1;p=t=()=>{c=!0};try{Ub(0),["stdout","stderr"].forEach(d=>{(d=Qb("/dev/"+d))&&mb[d.object.rdev]?.output?.length&&(c=!0)})}catch(d){}p=a;t=b;c&&z("stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the Emscripten FAQ), or make sure to emit a newline when you printf etc.")} +if(f.preInit)for("function"==typeof f.preInit&&(f.preInit=[f.preInit]);0{Ea=a;Fa=b});for(const a of Object.keys(f))a in moduleArg||Object.defineProperty(moduleArg,a,{configurable:!0,get(){v(`Access to module property ('${a}') is no longer possible via the module constructor argument; Instead, use the result of the module constructor.`)}}); +;return moduleRtn}export default Module; diff --git a/public/ghostscript-wasm/gs.wasm b/public/ghostscript-wasm/gs.wasm new file mode 100755 index 0000000..159cc23 Binary files /dev/null and b/public/ghostscript-wasm/gs.wasm differ diff --git a/public/ghostscript-wasm/sRGB_IEC61966-2-1_no_black_scaling.icc b/public/ghostscript-wasm/sRGB_IEC61966-2-1_no_black_scaling.icc new file mode 100644 index 0000000..d0ef573 Binary files /dev/null and b/public/ghostscript-wasm/sRGB_IEC61966-2-1_no_black_scaling.icc differ diff --git a/public/images/apple-touch-icon.png b/public/images/apple-touch-icon.png new file mode 100644 index 0000000..b2b9f30 Binary files /dev/null and b/public/images/apple-touch-icon.png differ diff --git a/public/images/favicon-192x192.png b/public/images/favicon-192x192.png new file mode 100644 index 0000000..7438a89 Binary files /dev/null and b/public/images/favicon-192x192.png differ diff --git a/public/images/favicon-512x512.png b/public/images/favicon-512x512.png new file mode 100644 index 0000000..7926d09 Binary files /dev/null and b/public/images/favicon-512x512.png differ diff --git a/public/images/favicon-no-bg.svg b/public/images/favicon-no-bg.svg new file mode 100644 index 0000000..01d9df7 --- /dev/null +++ b/public/images/favicon-no-bg.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/public/images/favicon.png b/public/images/favicon.png index a5fa7be..345a195 100644 Binary files a/public/images/favicon.png and b/public/images/favicon.png differ diff --git a/public/images/favicon.svg b/public/images/favicon.svg index 01d9df7..90ddc27 100644 --- a/public/images/favicon.svg +++ b/public/images/favicon.svg @@ -1,5 +1,7 @@ - + + + diff --git a/public/images/og-pdf-converter.png b/public/images/og-pdf-converter.png new file mode 100644 index 0000000..13f5c31 Binary files /dev/null and b/public/images/og-pdf-converter.png differ diff --git a/public/images/og-pdf-editor.png b/public/images/og-pdf-editor.png new file mode 100644 index 0000000..8c97d44 Binary files /dev/null and b/public/images/og-pdf-editor.png differ diff --git a/public/images/og-pdf-merge-split.png b/public/images/og-pdf-merge-split.png new file mode 100644 index 0000000..6104cf4 Binary files /dev/null and b/public/images/og-pdf-merge-split.png differ diff --git a/public/images/og-pdf-security.png b/public/images/og-pdf-security.png new file mode 100644 index 0000000..c98fd1b Binary files /dev/null and b/public/images/og-pdf-security.png differ diff --git a/public/images/og-tools.png b/public/images/og-tools.png new file mode 100644 index 0000000..f4e453d Binary files /dev/null and b/public/images/og-tools.png differ diff --git a/public/libreoffice-wasm/browser.worker.global.js b/public/libreoffice-wasm/browser.worker.global.js new file mode 100644 index 0000000..db95057 --- /dev/null +++ b/public/libreoffice-wasm/browser.worker.global.js @@ -0,0 +1,3 @@ +(function(){'use strict';var S=class extends Error{code;details;constructor(e,t,r){super(t),this.name="ConversionError",this.code=e,this.details=r;}},q={pdf:"writer_pdf_Export",docx:"MS Word 2007 XML",doc:"MS Word 97",odt:"writer8",rtf:"Rich Text Format",txt:"Text",html:"HTML (StarWriter)",xlsx:"Calc MS Excel 2007 XML",xls:"MS Excel 97",ods:"calc8",csv:"Text - txt - csv (StarCalc)",pptx:"Impress MS PowerPoint 2007 XML",ppt:"MS PowerPoint 97",odp:"impress8",png:"writer_png_Export",jpg:"writer_jpg_Export",svg:"writer_svg_Export"};var te={pdf:"application/pdf",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",doc:"application/msword",odt:"application/vnd.oasis.opendocument.text",rtf:"application/rtf",txt:"text/plain",html:"text/html",xlsx:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",xls:"application/vnd.ms-excel",ods:"application/vnd.oasis.opendocument.spreadsheet",csv:"text/csv",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",ppt:"application/vnd.ms-powerpoint",odp:"application/vnd.oasis.opendocument.presentation",png:"image/png",jpg:"image/jpeg",svg:"image/svg+xml"},re={doc:"doc",docx:"docx",xls:"xls",xlsx:"xlsx",ppt:"ppt",pptx:"pptx",odt:"odt",ods:"ods",odp:"odp",odg:"odg",odf:"odf",rtf:"rtf",txt:"txt",html:"html",htm:"html",csv:"csv",xml:"xml",epub:"epub",pdf:"pdf"},ge={0:["pdf","docx","doc","odt","rtf","txt","html","png"],1:["pdf","xlsx","xls","ods","csv","html","png"],2:["pdf","pptx","ppt","odp","png","svg","html"],3:["pdf","png","svg","html"],4:["pdf"]};function oe(l){return ge[l]||["pdf"]}var U={pdf:"pdf",docx:"docx",doc:"doc",odt:"odt",rtf:"rtf",txt:"txt",html:"html",xlsx:"xlsx",xls:"xls",ods:"ods",csv:"csv",pptx:"pptx",ppt:"ppt",odp:"odp",png:"png",jpg:"jpg",svg:"svg"},K={pdf:"",csv:"44,34,76,1,,0,false,true,false,false,false,-1",txt:"UTF8"},ne={doc:"text",docx:"text",odt:"text",rtf:"text",txt:"text",html:"text",htm:"text",epub:"text",xml:"text",xls:"spreadsheet",xlsx:"spreadsheet",ods:"spreadsheet",csv:"spreadsheet",ppt:"presentation",pptx:"presentation",odp:"presentation",odg:"drawing",odf:"drawing",pdf:"drawing"},fe={text:["pdf","docx","doc","odt","rtf","txt","html","png"],spreadsheet:["pdf","xlsx","xls","ods","csv","html","png"],presentation:["pdf","pptx","ppt","odp","png","svg","html"],drawing:["pdf","png","svg","html"],other:["pdf"]};function V(l){let e=l.toLowerCase(),t=ne[e];return t?fe[t]:["pdf"]}function ee(l,e){return V(l).includes(e.toLowerCase())}function ie(l,e){let t=l.toLowerCase(),r=e.toLowerCase(),n=V(t),o=ne[t]||"unknown",s="";return o==="drawing"&&["docx","doc","xlsx","xls","pptx","ppt"].includes(r)?s="PDF files are imported as Draw documents and cannot be exported to Office formats. ":o==="spreadsheet"&&["docx","doc","pptx","ppt"].includes(r)?s="Spreadsheet documents cannot be converted to word processing or presentation formats. ":o==="presentation"&&["docx","doc","xlsx","xls"].includes(r)?s="Presentation documents cannot be converted to word processing or spreadsheet formats. ":o==="text"&&["xlsx","xls","pptx","ppt"].includes(r)&&(s="Text documents cannot be converted to spreadsheet or presentation formats. "),`Cannot convert ${t.toUpperCase()} to ${r.toUpperCase()}. ${s}Valid output formats for ${t.toUpperCase()}: ${n.join(", ")}`}var I=class{lok;docPtr;options;inputPath="";constructor(e,t,r={}){this.lok=e,this.docPtr=t,this.options={maxResponseChars:r.maxResponseChars??8e3,...r};}getDocPtr(){return this.docPtr}getLokBindings(){return this.lok}save(){try{return this.inputPath?(this.lok.postUnoCommand(this.docPtr,".uno:Save"),this.createResult({path:this.inputPath})):this.createErrorResult("No input path set","Use saveAs() to specify a path")}catch(e){return this.createErrorResult(`Save failed: ${String(e)}`)}}saveAs(e,t){try{return this.lok.documentSaveAs(this.docPtr,e,t,""),this.createResult({path:e})}catch(r){return this.createErrorResult(`SaveAs failed: ${String(r)}`)}}close(){try{return this.lok.documentDestroy(this.docPtr),this.docPtr=0,this.createResult(void 0)}catch(e){return this.createErrorResult(`Close failed: ${String(e)}`)}}getEditMode(){return this.lok.getEditMode(this.docPtr)}enableEditMode(){try{if(this.lok.getEditMode(this.docPtr)===1)return this.createResult({editMode:1});this.lok.postUnoCommand(this.docPtr,".uno:Edit");let t=this.lok.getEditMode(this.docPtr);return {success:!0,verified:t===1,data:{editMode:t}}}catch(e){return this.createErrorResult(`Failed to enable edit mode: ${String(e)}`)}}undo(){try{return this.lok.postUnoCommand(this.docPtr,".uno:Undo"),this.createResult(void 0)}catch(e){return this.createErrorResult(`Undo failed: ${String(e)}`)}}redo(){try{return this.lok.postUnoCommand(this.docPtr,".uno:Redo"),this.createResult(void 0)}catch(e){return this.createErrorResult(`Redo failed: ${String(e)}`)}}find(e,t){try{let r=JSON.stringify({"SearchItem.SearchString":{type:"string",value:e},"SearchItem.Backward":{type:"boolean",value:!1},"SearchItem.SearchAll":{type:"boolean",value:!0},"SearchItem.MatchCase":{type:"boolean",value:t?.caseSensitive??!1},"SearchItem.WordOnly":{type:"boolean",value:t?.wholeWord??!1}});this.lok.postUnoCommand(this.docPtr,".uno:ExecuteSearch",r);let n=this.lok.getTextSelection(this.docPtr,"text/plain"),o=n!==null&&n.length>0;return this.createResult({matches:o?1:0,firstMatch:o?{x:0,y:0}:void 0})}catch(r){return this.createErrorResult(`Find failed: ${String(r)}`)}}findAndReplaceAll(e,t,r){try{let n=JSON.stringify({"SearchItem.SearchString":{type:"string",value:e},"SearchItem.ReplaceString":{type:"string",value:t},"SearchItem.Command":{type:"long",value:3},"SearchItem.MatchCase":{type:"boolean",value:r?.caseSensitive??!1},"SearchItem.WordOnly":{type:"boolean",value:r?.wholeWord??!1}});return this.lok.postUnoCommand(this.docPtr,".uno:ExecuteSearch",n),this.createResult({replacements:-1})}catch(n){return this.createErrorResult(`Replace failed: ${String(n)}`)}}getStateChanges(){try{let e=this.lok.pollStateChanges();return this.createResult(e)}catch(e){return this.createErrorResult(`Failed to poll state changes: ${String(e)}`)}}flushAndPollState(){try{this.lok.flushCallbacks(this.docPtr);let e=this.lok.pollStateChanges();return this.createResult(e)}catch(e){return this.createErrorResult(`Failed to flush and poll state: ${String(e)}`)}}clearCallbackQueue(){this.lok.clearCallbackQueue();}select(e){try{let t=this.lok.getTextSelection(this.docPtr,"text/plain");return this.createResult({selected:t||""})}catch(t){return this.createErrorResult(`Select failed: ${String(t)}`)}}getSelection(){try{let e=this.lok.getTextSelection(this.docPtr,"text/plain");return this.createResult({text:e||"",range:{type:"text",start:{paragraph:0,character:0}}})}catch(e){return this.createErrorResult(`GetSelection failed: ${String(e)}`)}}clearSelection(){try{return this.lok.resetSelection(this.docPtr),this.createResult(void 0)}catch(e){return this.createErrorResult(`ClearSelection failed: ${String(e)}`)}}createResult(e){return {success:true,verified:true,data:e}}createErrorResult(e,t){return {success:false,verified:false,error:e,suggestion:t}}createResultWithTruncation(e,t){return {success:true,verified:true,data:e,truncated:t}}truncateContent(e,t){let r=t??this.options.maxResponseChars,n=e.length;if(n<=r)return {content:e,truncated:false,original:n,returned:n};let o=e.slice(0,r),s=o.lastIndexOf(" ");return s>r*.8&&(o=o.slice(0,s)),{content:o,truncated:true,original:n,returned:o.length}}truncateArray(e,t,r){let n=e.length,o=0,s=0;for(let i of e){let a=r(i);if(o+a.length>t)break;o+=a.length,s++;}return {items:e.slice(0,s),truncated:s0;){let o=(n-1)%26;r=String.fromCharCode(65+o)+r,n=Math.floor((n-1)/26);}return `${r}${e+1}`}normalizeCellRef(e){return typeof e=="string"?this.a1ToRowCol(e):e}setInputPath(e){this.inputPath=e;}isOpen(){return this.docPtr!==0}};var z=class extends I{cachedParagraphs=null;getDocumentType(){return "writer"}getStructure(e){try{let t=this.getParagraphsInternal(),r=e?.maxResponseChars??this.options.maxResponseChars,n=t.map((i,a)=>({index:a,preview:i.slice(0,100)+(i.length>100?"...":""),style:"Normal",charCount:i.length})),o=this.truncateArray(n,r,i=>JSON.stringify(i)),s={type:"writer",paragraphs:o.items,pageCount:this.lok.documentGetParts(this.docPtr),wordCount:t.join(" ").split(/\s+/).filter(i=>i.length>0).length};return o.truncated?this.createResultWithTruncation(s,{original:o.original,returned:o.returned,message:`Showing ${o.returned} of ${o.original} paragraphs. Use getParagraphs(start, count) to paginate.`}):this.createResult(s)}catch(t){return this.createErrorResult(`Failed to get structure: ${String(t)}`)}}getParagraph(e){try{let t=this.getParagraphsInternal();if(e<0||e>=t.length)return this.createErrorResult(`Paragraph index ${e} out of range (0-${t.length-1})`,"Use getStructure() to see available paragraphs");let r=t[e];return this.createResult({index:e,text:r,style:"Normal",charCount:r.length})}catch(t){return this.createErrorResult(`Failed to get paragraph: ${String(t)}`)}}getParagraphs(e,t){try{let r=this.getParagraphsInternal();if(e<0||e>=r.length)return this.createErrorResult(`Start index ${e} out of range`,`Valid range: 0-${r.length-1}`);let n=Math.min(e+t,r.length),o=r.slice(e,n).map((s,i)=>({index:e+i,text:s,style:"Normal",charCount:s.length}));return this.createResult(o)}catch(r){return this.createErrorResult(`Failed to get paragraphs: ${String(r)}`)}}insertParagraph(e,t){try{let r=this.getParagraphsInternal(),n=t?.afterIndex!==void 0?t.afterIndex+1:r.length;n>0&&n<=r.length&&this.lok.postUnoCommand(this.docPtr,".uno:GoToEndOfDoc"),this.lok.postUnoCommand(this.docPtr,".uno:InsertPara");let o=JSON.stringify({Text:{type:"string",value:e}});if(this.lok.postUnoCommand(this.docPtr,".uno:InsertText",o),t?.style&&t.style!=="Normal"){let d={"Heading 1":"Heading 1","Heading 2":"Heading 2","Heading 3":"Heading 3",List:"List"}[t.style];if(d){let h=JSON.stringify({Template:{type:"string",value:d},Family:{type:"short",value:2}});this.lok.postUnoCommand(this.docPtr,".uno:StyleApply",h);}}return this.cachedParagraphs=null,{success:!0,verified:this.getParagraphsInternal().length>r.length,data:{index:n}}}catch(r){return this.createErrorResult(`Failed to insert paragraph: ${String(r)}`)}}replaceParagraph(e,t){try{let r=this.getParagraphsInternal();if(e<0||e>=r.length)return this.createErrorResult(`Paragraph index ${e} out of range`,`Valid range: 0-${r.length-1}`);let n=r[e],o=JSON.stringify({"SearchItem.SearchString":{type:"string",value:n},"SearchItem.ReplaceString":{type:"string",value:t},"SearchItem.Command":{type:"long",value:2}});return this.lok.postUnoCommand(this.docPtr,".uno:ExecuteSearch",o),this.cachedParagraphs=null,this.createResult({oldText:n})}catch(r){return this.createErrorResult(`Failed to replace paragraph: ${String(r)}`)}}deleteParagraph(e){try{let t=this.getParagraphsInternal();if(e<0||e>=t.length)return this.createErrorResult(`Paragraph index ${e} out of range`,`Valid range: 0-${t.length-1}`);let r=t[e],n=this.replaceParagraph(e,"");return n.success?this.createResult({deletedText:r}):this.createErrorResult(n.error||"Failed to delete")}catch(t){return this.createErrorResult(`Failed to delete paragraph: ${String(t)}`)}}insertText(e,t){try{let r=JSON.stringify({Text:{type:"string",value:e}});return this.lok.postUnoCommand(this.docPtr,".uno:InsertText",r),this.cachedParagraphs=null,this.createResult(void 0)}catch(r){return this.createErrorResult(`Failed to insert text: ${String(r)}`)}}deleteText(e,t){try{let r=this.lok.getTextSelection(this.docPtr,"text/plain");return this.lok.postUnoCommand(this.docPtr,".uno:Delete"),this.cachedParagraphs=null,this.createResult({deleted:r||""})}catch(r){return this.createErrorResult(`Failed to delete text: ${String(r)}`)}}replaceText(e,t,r){try{let n=r?.all?3:2,o=JSON.stringify({"SearchItem.SearchString":{type:"string",value:e},"SearchItem.ReplaceString":{type:"string",value:t},"SearchItem.Command":{type:"long",value:n}});return this.lok.postUnoCommand(this.docPtr,".uno:ExecuteSearch",o),this.cachedParagraphs=null,this.createResult({replacements:-1})}catch(n){return this.createErrorResult(`Failed to replace text: ${String(n)}`)}}formatText(e,t){try{if(t.bold!==void 0&&this.lok.postUnoCommand(this.docPtr,".uno:Bold"),t.italic!==void 0&&this.lok.postUnoCommand(this.docPtr,".uno:Italic"),t.underline!==void 0&&this.lok.postUnoCommand(this.docPtr,".uno:Underline"),t.fontSize!==void 0){let r=JSON.stringify({FontHeight:{type:"float",value:t.fontSize}});this.lok.postUnoCommand(this.docPtr,".uno:FontHeight",r);}if(t.fontName!==void 0){let r=JSON.stringify({CharFontName:{type:"string",value:t.fontName}});this.lok.postUnoCommand(this.docPtr,".uno:CharFontName",r);}return this.createResult(void 0)}catch(r){return this.createErrorResult(`Failed to format text: ${String(r)}`)}}getFormat(e){try{this.lok.clearCallbackQueue(),this.lok.postUnoCommand(this.docPtr,".uno:CharRightSel"),this.lok.flushCallbacks(this.docPtr),this.lok.postUnoCommand(this.docPtr,".uno:CharLeft"),this.lok.flushCallbacks(this.docPtr);let t=this.lok.pollStateChanges(),r={},n=t.get(".uno:Bold");n!==void 0&&(r.bold=n==="true");let o=t.get(".uno:Italic");o!==void 0&&(r.italic=o==="true");let s=t.get(".uno:Underline");s!==void 0&&(r.underline=s==="true");let i=t.get(".uno:FontHeight");if(i!==void 0){let d=parseFloat(i);isNaN(d)||(r.fontSize=d);}let a=t.get(".uno:CharFontName");return a!==void 0&&a.length>0&&(r.fontName=a),this.createResult(r)}catch(t){return this.createErrorResult(`Failed to get format: ${String(t)}`)}}getSelectionFormat(){try{let e=this.lok.pollStateChanges();if(e.size===0){this.lok.clearCallbackQueue(),this.lok.postUnoCommand(this.docPtr,".uno:SelectWord"),this.lok.flushCallbacks(this.docPtr);let t=this.lok.pollStateChanges();return this.createResult(t)}return this.createResult(e)}catch(e){return this.createErrorResult(`Failed to get selection format: ${String(e)}`)}}getParagraphsInternal(){if(this.cachedParagraphs)return this.cachedParagraphs;let e=this.lok.getAllText(this.docPtr);return e?(this.cachedParagraphs=e.split(/\n\n|\r\n\r\n/).map(t=>t.trim()).filter(t=>t.length>0),this.cachedParagraphs):[]}};var G=class extends I{getDocumentType(){return "calc"}getStructure(e){try{let t=this.lok.documentGetParts(this.docPtr),r=[];for(let o=0;o0&&i.row>0?`A1:${this.rowColToA1(i.row-1,i.col-1)}`:"A1",rowCount:i.row,colCount:i.col});}let n={type:"calc",sheets:r};return this.createResult(n)}catch(t){return this.createErrorResult(`Failed to get structure: ${String(t)}`)}}getSheetNames(){try{let e=this.lok.documentGetParts(this.docPtr),t=[];for(let r=0;ra){m=!0;break}h+=_.length,g.push(O);}g.length>0&&d.push(g);}return m?this.createResultWithTruncation(d,{original:(s-n+1)*(i-o+1),returned:d.reduce((u,g)=>u+g.length,0),message:"Range truncated due to size. Use smaller ranges to paginate."}):this.createResult(d)}catch(n){return this.createErrorResult(`Failed to get cells: ${String(n)}`)}}setCellValue(e,t,r){try{this.selectSheet(r);let{row:n,col:o}=this.normalizeCellRef(e),s=this.rowColToA1(n,o);this.goToCell(s);let i=this.getCellValueInternal(),a=typeof t=="number"?t.toString():t,d=JSON.stringify({StringName:{type:"string",value:a}});this.lok.postUnoCommand(this.docPtr,".uno:EnterString",d);let h=this.getCellValueInternal(),m=typeof t=="number"?t.toString():t;return {success:!0,verified:h===m||h===t,data:{oldValue:i,newValue:h}}}catch(n){return this.createErrorResult(`Failed to set cell value: ${String(n)}`)}}setCellFormula(e,t,r){try{this.selectSheet(r);let{row:n,col:o}=this.normalizeCellRef(e),s=this.rowColToA1(n,o);this.goToCell(s);let i=JSON.stringify({StringName:{type:"string",value:t}});this.lok.postUnoCommand(this.docPtr,".uno:EnterString",i);let a=this.getCellValueInternal();return this.createResult({calculatedValue:a})}catch(n){return this.createErrorResult(`Failed to set formula: ${String(n)}`)}}setCells(e,t,r){try{this.selectSheet(r);let{startRow:n,startCol:o}=this.normalizeRangeRef(e),s=0;for(let i=0;i=0&&this.lok.documentSetPart(this.docPtr,t);}getSheetIndexByName(e){let t=this.lok.documentGetParts(this.docPtr);for(let r=0;r=t)return this.createErrorResult(`Invalid slide index: ${e}. Valid range: 0-${t-1}`,"Use getStructure() to see available slides");this.lok.documentSetPart(this.docPtr,e);let r=this.lok.getAllText(this.docPtr)||"",n=this.parseTextFrames(r),o={index:e,title:n.find(s=>s.type==="title")?.text,textFrames:n,hasNotes:!1};return this.createResult(o)}catch(t){return this.createErrorResult(`Failed to get slide: ${String(t)}`)}}getSlideCount(){try{let e=this.lok.documentGetParts(this.docPtr);return this.createResult(e)}catch(e){return this.createErrorResult(`Failed to get slide count: ${String(e)}`)}}addSlide(e){try{let t=this.lok.documentGetParts(this.docPtr);e?.afterSlide!==void 0?this.lok.documentSetPart(this.docPtr,e.afterSlide):this.lok.documentSetPart(this.docPtr,t-1),this.lok.postUnoCommand(this.docPtr,".uno:InsertPage"),e?.layout&&this.applySlideLayout(e.layout);let r=e?.afterSlide!==void 0?e.afterSlide+1:t;return {success:!0,verified:this.lok.documentGetParts(this.docPtr)>t,data:{index:r}}}catch(t){return this.createErrorResult(`Failed to add slide: ${String(t)}`)}}deleteSlide(e){try{let t=this.lok.documentGetParts(this.docPtr);return t<=1?this.createErrorResult("Cannot delete the last slide","A presentation must have at least one slide"):e<0||e>=t?this.createErrorResult(`Invalid slide index: ${e}`,`Valid range: 0-${t-1}`):(this.lok.documentSetPart(this.docPtr,e),this.lok.postUnoCommand(this.docPtr,".uno:DeletePage"),this.createResult(void 0))}catch(t){return this.createErrorResult(`Failed to delete slide: ${String(t)}`)}}duplicateSlide(e){try{let t=this.lok.documentGetParts(this.docPtr);return e<0||e>=t?this.createErrorResult(`Invalid slide index: ${e}`,`Valid range: 0-${t-1}`):(this.lok.documentSetPart(this.docPtr,e),this.lok.postUnoCommand(this.docPtr,".uno:DuplicatePage"),this.createResult({newIndex:e+1}))}catch(t){return this.createErrorResult(`Failed to duplicate slide: ${String(t)}`)}}moveSlide(e,t){try{let r=this.lok.documentGetParts(this.docPtr);if(e<0||e>=r||t<0||t>=r)return this.createErrorResult(`Invalid slide indices. Valid range: 0-${r-1}`,"Check slide indices are within bounds");if(e===t)return this.createErrorResult("Source and destination are the same","Provide different indices to move");this.lok.documentSetPart(this.docPtr,e);let n=JSON.stringify({Position:{type:"long",value:t}});return this.lok.postUnoCommand(this.docPtr,".uno:MovePageFirst",n),this.createResult(void 0)}catch(r){return this.createErrorResult(`Failed to move slide: ${String(r)}`)}}setSlideTitle(e,t){try{let r=this.lok.documentGetParts(this.docPtr);if(e<0||e>=r)return this.createErrorResult(`Invalid slide index: ${e}`);this.lok.documentSetPart(this.docPtr,e);let n=this.lok.getAllText(this.docPtr)||"",s=this.parseTextFrames(n).find(a=>a.type==="title")?.text;this.lok.postUnoCommand(this.docPtr,".uno:SelectAll");let i=JSON.stringify({Text:{type:"string",value:t}});return this.lok.postUnoCommand(this.docPtr,".uno:InsertText",i),this.createResult({oldTitle:s})}catch(r){return this.createErrorResult(`Failed to set slide title: ${String(r)}`)}}setSlideBody(e,t){try{let r=this.lok.documentGetParts(this.docPtr);if(e<0||e>=r)return this.createErrorResult(`Invalid slide index: ${e}`);this.lok.documentSetPart(this.docPtr,e);let n=this.lok.getAllText(this.docPtr)||"",s=this.parseTextFrames(n).find(a=>a.type==="body")?.text;this.lok.postUnoCommand(this.docPtr,".uno:NextObject");let i=JSON.stringify({Text:{type:"string",value:t}});return this.lok.postUnoCommand(this.docPtr,".uno:InsertText",i),this.createResult({oldBody:s})}catch(r){return this.createErrorResult(`Failed to set slide body: ${String(r)}`)}}setSlideNotes(e,t){try{let r=this.lok.documentGetParts(this.docPtr);if(e<0||e>=r)return this.createErrorResult(`Invalid slide index: ${e}`);this.lok.documentSetPart(this.docPtr,e),this.lok.postUnoCommand(this.docPtr,".uno:NotesMode");let n=JSON.stringify({Text:{type:"string",value:t}});return this.lok.postUnoCommand(this.docPtr,".uno:InsertText",n),this.lok.postUnoCommand(this.docPtr,".uno:NormalViewMode"),this.createResult(void 0)}catch(r){return this.createErrorResult(`Failed to set slide notes: ${String(r)}`)}}setSlideLayout(e,t){try{let r=this.lok.documentGetParts(this.docPtr);return e<0||e>=r?this.createErrorResult(`Invalid slide index: ${e}`):(this.lok.documentSetPart(this.docPtr,e),this.applySlideLayout(t),this.createResult(void 0))}catch(r){return this.createErrorResult(`Failed to set slide layout: ${String(r)}`)}}getSlideInfoInternal(e){this.lok.documentSetPart(this.docPtr,e);let t=this.lok.getAllText(this.docPtr)||"",r=this.parseTextFrames(t),n=r.find(o=>o.type==="title");return {index:e,title:n?.text,layout:this.detectLayout(r),textFrameCount:r.length}}parseTextFrames(e){let t=e.split(/\n\n+/).filter(n=>n.trim()),r=[];return t.forEach((n,o)=>{let s=o===0?"title":o===1?"body":"other";r.push({index:o,type:s,text:n.trim(),bounds:{x:0,y:0,width:0,height:0}});}),r}detectLayout(e){return e.length===0?"blank":e.length===1&&e[0]?.type==="title"?"title":e.length>=2?"titleContent":"blank"}applySlideLayout(e){let r={blank:0,title:1,titleContent:2,twoColumn:3}[e]??0,n=JSON.stringify({WhatLayout:{type:"long",value:r}});this.lok.postUnoCommand(this.docPtr,".uno:AssignLayout",n);}};var j=class extends I{isImportedPdf=false;getDocumentType(){return "draw"}setImportedPdf(e){this.isImportedPdf=e;}getStructure(e){try{let t=this.lok.documentGetParts(this.docPtr),r=[];for(let o=0;o=t)return this.createErrorResult(`Invalid page index: ${e}. Valid range: 0-${t-1}`,"Use getStructure() to see available pages");this.lok.documentSetPart(this.docPtr,e);let r=this.lok.documentGetDocumentSize(this.docPtr),n=this.getShapesOnPage(),o={index:e,shapes:n,size:{width:r.width,height:r.height}};return this.createResult(o)}catch(t){return this.createErrorResult(`Failed to get page: ${String(t)}`)}}getPageCount(){try{let e=this.lok.documentGetParts(this.docPtr);return this.createResult(e)}catch(e){return this.createErrorResult(`Failed to get page count: ${String(e)}`)}}addPage(e){try{let t=this.lok.documentGetParts(this.docPtr);e?.afterPage!==void 0?this.lok.documentSetPart(this.docPtr,e.afterPage):this.lok.documentSetPart(this.docPtr,t-1),this.lok.postUnoCommand(this.docPtr,".uno:InsertPage");let r=e?.afterPage!==void 0?e.afterPage+1:t;return this.createResult({index:r})}catch(t){return this.createErrorResult(`Failed to add page: ${String(t)}`)}}deletePage(e){try{let t=this.lok.documentGetParts(this.docPtr);return t<=1?this.createErrorResult("Cannot delete the last page","A drawing document must have at least one page"):e<0||e>=t?this.createErrorResult(`Invalid page index: ${e}`,`Valid range: 0-${t-1}`):(this.lok.documentSetPart(this.docPtr,e),this.lok.postUnoCommand(this.docPtr,".uno:DeletePage"),this.createResult(void 0))}catch(t){return this.createErrorResult(`Failed to delete page: ${String(t)}`)}}duplicatePage(e){try{let t=this.lok.documentGetParts(this.docPtr);return e<0||e>=t?this.createErrorResult(`Invalid page index: ${e}`,`Valid range: 0-${t-1}`):(this.lok.documentSetPart(this.docPtr,e),this.lok.postUnoCommand(this.docPtr,".uno:DuplicatePage"),this.createResult({newIndex:e+1}))}catch(t){return this.createErrorResult(`Failed to duplicate page: ${String(t)}`)}}addShape(e,t,r,n){try{let o=this.lok.documentGetParts(this.docPtr);if(e<0||e>=o)return this.createErrorResult(`Invalid page index: ${e}`);this.lok.documentSetPart(this.docPtr,e);let s=this.getShapeCommand(t),i=JSON.stringify({X:{type:"long",value:r.x},Y:{type:"long",value:r.y},Width:{type:"long",value:r.width},Height:{type:"long",value:r.height}});if(this.lok.postUnoCommand(this.docPtr,s,i),n?.text){let a=JSON.stringify({Text:{type:"string",value:n.text}});this.lok.postUnoCommand(this.docPtr,".uno:InsertText",a);}if(n?.fillColor){let a=JSON.stringify({FillColor:{type:"long",value:this.hexToNumber(n.fillColor)}});this.lok.postUnoCommand(this.docPtr,".uno:FillColor",a);}if(n?.lineColor){let a=JSON.stringify({LineColor:{type:"long",value:this.hexToNumber(n.lineColor)}});this.lok.postUnoCommand(this.docPtr,".uno:XLineColor",a);}return this.createResult({shapeIndex:0})}catch(o){return this.createErrorResult(`Failed to add shape: ${String(o)}`)}}addLine(e,t,r,n){try{let o=this.lok.documentGetParts(this.docPtr);if(e<0||e>=o)return this.createErrorResult(`Invalid page index: ${e}`);this.lok.documentSetPart(this.docPtr,e);let s=JSON.stringify({StartX:{type:"long",value:t.x},StartY:{type:"long",value:t.y},EndX:{type:"long",value:r.x},EndY:{type:"long",value:r.y}});if(this.lok.postUnoCommand(this.docPtr,".uno:Line",s),n?.lineColor){let i=JSON.stringify({LineColor:{type:"long",value:this.hexToNumber(n.lineColor)}});this.lok.postUnoCommand(this.docPtr,".uno:XLineColor",i);}if(n?.lineWidth){let i=JSON.stringify({LineWidth:{type:"long",value:n.lineWidth}});this.lok.postUnoCommand(this.docPtr,".uno:LineWidth",i);}return this.createResult({shapeIndex:0})}catch(o){return this.createErrorResult(`Failed to add line: ${String(o)}`)}}deleteShape(e,t){try{return this.lok.documentSetPart(this.docPtr,e),this.selectShape(t),this.lok.postUnoCommand(this.docPtr,".uno:Delete"),this.createResult(void 0)}catch(r){return this.createErrorResult(`Failed to delete shape: ${String(r)}`)}}setShapeText(e,t,r){try{this.lok.documentSetPart(this.docPtr,e),this.selectShape(t),this.lok.postUnoCommand(this.docPtr,".uno:EnterGroup"),this.lok.postUnoCommand(this.docPtr,".uno:SelectAll");let n=JSON.stringify({Text:{type:"string",value:r}});return this.lok.postUnoCommand(this.docPtr,".uno:InsertText",n),this.lok.postUnoCommand(this.docPtr,".uno:LeaveGroup"),this.createResult(void 0)}catch(n){return this.createErrorResult(`Failed to set shape text: ${String(n)}`)}}moveShape(e,t,r){try{this.lok.documentSetPart(this.docPtr,e),this.selectShape(t);let n=JSON.stringify({X:{type:"long",value:r.x},Y:{type:"long",value:r.y}});return this.lok.postUnoCommand(this.docPtr,".uno:SetObjectPosition",n),this.createResult(void 0)}catch(n){return this.createErrorResult(`Failed to move shape: ${String(n)}`)}}resizeShape(e,t,r){try{this.lok.documentSetPart(this.docPtr,e),this.selectShape(t);let n=JSON.stringify({Width:{type:"long",value:r.width},Height:{type:"long",value:r.height}});return this.lok.postUnoCommand(this.docPtr,".uno:Size",n),this.createResult(void 0)}catch(n){return this.createErrorResult(`Failed to resize shape: ${String(n)}`)}}getPageInfoInternal(e){this.lok.documentSetPart(this.docPtr,e);let t=this.lok.documentGetDocumentSize(this.docPtr),r=this.getShapesOnPage();return {index:e,shapeCount:r.length,size:{width:t.width,height:t.height}}}getShapesOnPage(){let e=this.lok.getAllText(this.docPtr)||"";return e.trim()?[{index:0,type:"text",text:e,bounds:{x:0,y:0,width:0,height:0}}]:[]}selectShape(e){let t=JSON.stringify({Index:{type:"long",value:e}});this.lok.postUnoCommand(this.docPtr,".uno:SelectObject",t);}getShapeCommand(e){return {rectangle:".uno:Rect",ellipse:".uno:Ellipse",line:".uno:Line",text:".uno:Text",image:".uno:InsertGraphic",group:".uno:FormatGroup",other:".uno:Rect"}[e]}hexToNumber(e){return parseInt(e.replace("#",""),16)}};var ye=0,Se=1,Ee=2,Pe=3;function se(l,e,t){let r=l.documentGetDocumentType(e);switch(r){case ye:return new z(l,e,t);case Se:return new G(l,e,t);case Ee:return new H(l,e,t);case Pe:return new j(l,e,t);default:throw new Error(`Unsupported document type: ${r}`)}}function Oe(l){return {0:"INVALIDATE_TILES",1:"INVALIDATE_VISIBLE_CURSOR",2:"TEXT_SELECTION",3:"TEXT_SELECTION_START",4:"TEXT_SELECTION_END",5:"CURSOR_VISIBLE",6:"GRAPHIC_SELECTION",7:"HYPERLINK_CLICKED",8:"STATE_CHANGED",9:"STATUS_INDICATOR_START",10:"STATUS_INDICATOR_SET_VALUE",11:"STATUS_INDICATOR_FINISH",12:"SEARCH_NOT_FOUND",13:"DOCUMENT_SIZE_CHANGED",14:"SET_PART",15:"SEARCH_RESULT_SELECTION",16:"UNO_COMMAND_RESULT",17:"CELL_CURSOR",18:"MOUSE_POINTER",19:"CELL_FORMULA",20:"DOCUMENT_PASSWORD",21:"DOCUMENT_PASSWORD_TO_MODIFY",22:"CONTEXT_MENU",23:"INVALIDATE_VIEW_CURSOR",24:"TEXT_VIEW_SELECTION",25:"CELL_VIEW_CURSOR",26:"GRAPHIC_VIEW_SELECTION",27:"VIEW_CURSOR_VISIBLE",28:"VIEW_LOCK",29:"REDLINE_TABLE_SIZE_CHANGED",30:"REDLINE_TABLE_ENTRY_MODIFIED",31:"COMMENT",32:"INVALIDATE_HEADER",33:"CELL_ADDRESS"}[l]||`UNKNOWN(${l})`}var J={nSize:0,destroy:4,documentLoad:8,getError:12,documentLoadWithOptions:16,freeError:20},ae={nSize:0,destroy:4,saveAs:8},_e=new TextEncoder,le=new TextDecoder,X=class{module;lokPtr=0;verbose;useShims;constructor(e,t=false){this.module=e,this.verbose=t,this.useShims=typeof this.module._lok_documentLoad=="function",this.useShims?this.log("Using direct LOK shim exports"):this.log("Using vtable traversal (shims not available)");}log(...e){this.verbose&&console.log("[LOK]",...e);}get HEAPU8(){return this.module.HEAPU8}get HEAPU32(){return this.module.HEAPU32}get HEAP32(){return this.module.HEAP32}allocString(e){let t=_e.encode(e+"\0"),r=this.module._malloc(t.length);return this.HEAPU8.set(t,r),r}readString(e){if(e===0)return null;let t=this.HEAPU8,r=e;for(;t[r]!==0;)r++;let n=t.slice(e,r);return le.decode(n)}readPtr(e){return this.HEAPU32[e>>2]||0}getFunc(e){return this.module.wasmTable.get(e)}initialize(e="/instdir/program"){this.log("Initializing with path:",e);let t=this.allocString(e);try{let r=this.module._libreofficekit_hook;if(typeof r!="function")throw new Error("libreofficekit_hook export not found on module");if(this.lokPtr=r(t),this.lokPtr===0)throw new Error("Failed to initialize LibreOfficeKit");this.log("LOK initialized, ptr:",this.lokPtr);}finally{this.module._free(t);}}getError(){if(this.lokPtr===0)return null;if(this.useShims&&this.module._lok_getError){let o=this.module._lok_getError(this.lokPtr);return this.readString(o)}let e=this.readPtr(this.lokPtr),t=this.readPtr(e+J.getError);if(t===0)return null;let n=this.getFunc(t)(this.lokPtr);return this.readString(n)}getVersionInfo(){return "LibreOffice WASM"}toFileUrl(e){return e.startsWith("file://")?e:"file://"+(e.startsWith("/")?e:"/"+e)}documentLoad(e){if(this.lokPtr===0)throw new Error("LOK not initialized");let t=this.toFileUrl(e);this.log("Loading document:",e,"->",t);let r=this.allocString(t);try{let n=Date.now(),o;if(this.useShims&&this.module._lok_documentLoad)o=this.module._lok_documentLoad(this.lokPtr,r);else {let s=this.readPtr(this.lokPtr),i=this.readPtr(s+J.documentLoad);o=this.getFunc(i)(this.lokPtr,r);}if(this.log("Document loaded in",Date.now()-n,"ms, ptr:",o),o===0){let s=this.getError();throw new Error(`Failed to load document: ${s||"unknown error"}`)}return o}finally{this.module._free(r);}}documentLoadWithOptions(e,t){if(this.lokPtr===0)throw new Error("LOK not initialized");let r=this.toFileUrl(e);this.log("Loading document with options:",e,"->",r,t);let n=this.allocString(r),o=this.allocString(t);try{let s;if(this.useShims&&this.module._lok_documentLoadWithOptions)s=this.module._lok_documentLoadWithOptions(this.lokPtr,n,o);else {let i=this.readPtr(this.lokPtr),a=this.readPtr(i+J.documentLoadWithOptions);if(a===0)return this.documentLoad(e);s=this.getFunc(a)(this.lokPtr,n,o);}if(s===0){let i=this.getError();throw new Error(`Failed to load document: ${i||"unknown error"}`)}return this.log("Document loaded, ptr:",s),s}finally{this.module._free(n),this.module._free(o);}}documentSaveAs(e,t,r,n=""){if(e===0)throw new Error("Invalid document pointer");let o=this.toFileUrl(t);this.log("Saving document to:",t,"->",o,"format:",r);let s=this.allocString(o),i=this.allocString(r),a=this.allocString(n);try{let d;if(this.useShims&&this.module._lok_documentSaveAs)d=this.module._lok_documentSaveAs(e,s,i,a);else {let h=this.readPtr(e),m=this.readPtr(h+ae.saveAs);d=this.getFunc(m)(e,s,i,a);}if(this.log("Save result:",d),d===0)throw new Error("Failed to save document")}finally{this.module._free(s),this.module._free(i),this.module._free(a);}}documentDestroy(e){if(e===0)return;if(this.useShims&&this.module._lok_documentDestroy){this.module._lok_documentDestroy(e),this.log("Document destroyed (via shim)");return}let t=this.readPtr(e),r=this.readPtr(t+ae.destroy);r!==0&&(this.getFunc(r)(e),this.log("Document destroyed (via vtable)"));}destroy(){if(this.lokPtr!==0){try{if(this.useShims&&this.module._lok_destroy)this.module._lok_destroy(this.lokPtr),this.log("LOK destroyed (via shim)");else {let e=this.readPtr(this.lokPtr),t=this.readPtr(e+J.destroy);t!==0&&(this.getFunc(t)(this.lokPtr),this.log("LOK destroyed (via vtable)"));}}catch(e){this.log("LOK destroy error (ignored):",e);}this.lokPtr=0;}}isInitialized(){return this.lokPtr!==0}isUsingShims(){return this.useShims}documentGetParts(e){if(e===0)throw new Error("Invalid document pointer");return this.useShims&&this.module._lok_documentGetParts?this.module._lok_documentGetParts(e):(this.log("documentGetParts: shim not available"),0)}documentGetPart(e){if(e===0)throw new Error("Invalid document pointer");return this.useShims&&this.module._lok_documentGetPart?this.module._lok_documentGetPart(e):(this.log("documentGetPart: shim not available"),0)}documentSetPart(e,t){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentSetPart){this.module._lok_documentSetPart(e,t);return}this.log("documentSetPart: shim not available");}documentGetDocumentType(e){if(e===0)throw new Error("Invalid document pointer");return this.useShims&&this.module._lok_documentGetDocumentType?this.module._lok_documentGetDocumentType(e):(this.log("documentGetDocumentType: shim not available"),0)}documentGetDocumentSize(e){if(this.log(`documentGetDocumentSize called with docPtr: ${e}`),e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentGetDocumentSize){let t=this.module._malloc(8);try{this.module._lok_documentGetDocumentSize(e,t,t+4);let r=this.HEAP32[t>>2]??0,n=this.HEAP32[t+4>>2]??0;return this.log(`documentGetDocumentSize: ${r}x${n} twips`),{width:r,height:n}}finally{this.module._free(t);}}return this.log("documentGetDocumentSize: shim not available"),{width:0,height:0}}documentInitializeForRendering(e,t=""){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentInitializeForRendering){let r=this.allocString(t);try{this.module._lok_documentInitializeForRendering(e,r);}finally{this.module._free(r);}return}this.log("documentInitializeForRendering: shim not available");}documentPaintTile(e,t,r,n,o,s,i){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentPaintTile){let a=t*r*4,d=this.module._malloc(a);if(d===0)throw new Error(`Failed to allocate ${a} bytes for tile buffer`);try{this.module._lok_documentPaintTile(e,d,t,r,n,o,s,i);let h=new Uint8Array(a);return h.set(this.HEAPU8.subarray(d,d+a)),h}finally{this.module._free(d);}}return this.log("documentPaintTile: shim not available"),new Uint8Array(0)}documentGetTileMode(e){if(e===0)throw new Error("Invalid document pointer");return this.useShims&&this.module._lok_documentGetTileMode?this.module._lok_documentGetTileMode(e):(this.log("documentGetTileMode: shim not available"),0)}renderPage(e,t,r,n=0,o=false){this.documentInitializeForRendering(e);let s=this.documentGetDocumentType(e);if(s===2||s===3){console.log(`[LOK] Setting part to ${t} for presentation/drawing`),this.documentSetPart(e,t);let p=this.documentGetPart(e);console.log(`[LOK] Current part after setPart: ${p}`),o||(this.setEditMode(e,0),console.log("[LOK] Set edit mode to 0 (view mode) for presentation rendering"));}let i=this.documentGetDocumentSize(e);if(this.log("Document size (twips):",i),i.width===0||i.height===0)throw new Error("Failed to get document size");let a=0,d=0,h=i.width,m=i.height;if(s===0||s===1){let p=this.getPartPageRectangles(e);if(p){let _=this.parsePageRectangles(p)[t];_&&(a=_.x,d=_.y,h=_.width,m=_.height,this.log(`Page ${t} rectangle:`,_));}}let u=m/h,g=r,f=n>0?n:Math.round(r*u);console.log(`[LOK] Calling paintTile: ${g}x${f} from tile pos (${a}, ${d}) size (${h}x${m})`);let P=this.documentPaintTile(e,g,f,a,d,h,m);return console.log(`[LOK] paintTile returned ${P.length} bytes`),{data:P,width:g,height:f}}renderPageFullQuality(e,t,r=150,n,o=false){this.documentInitializeForRendering(e);let s=this.documentGetDocumentType(e);(s===2||s===3)&&(this.log(`Setting part to ${t} for presentation/drawing`),this.documentSetPart(e,t),o||(this.setEditMode(e,0),this.log("Set edit mode to 0 (view mode) for presentation rendering")));let i=this.documentGetDocumentSize(e);if(this.log("Document size (twips):",i),i.width===0||i.height===0)throw new Error("Failed to get document size");let a=0,d=0,h=i.width,m=i.height;if(s===0||s===1){let O=this.getPartPageRectangles(e);if(O){let k=this.parsePageRectangles(O)[t];k&&(a=k.x,d=k.y,h=k.width,m=k.height,this.log(`Page ${t} rectangle:`,k));}}let u=1440,g=Math.round(h*r/u),f=Math.round(m*r/u),P=r;if(n&&(g>n||f>n)){let O=n/Math.max(g,f);g=Math.round(g*O),f=Math.round(f*O),P=Math.round(r*O),this.log(`Capped dimensions to ${g}x${f} (effective DPI: ${P})`);}console.log(`[LOK] renderPageFullQuality: ${g}x${f} at ${P} DPI from tile (${a}, ${d}) size (${h}x${m}) twips`);let p=this.documentPaintTile(e,g,f,a,d,h,m);return console.log(`[LOK] renderPageFullQuality returned ${p.length} bytes`),{data:p,width:g,height:f,dpi:P}}getTextSelection(e,t="text/plain;charset=utf-8"){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentGetTextSelection){let r=this.allocString(t),n=this.module._malloc(4);try{let o=this.module._lok_documentGetTextSelection(e,r,n);if(o===0)return null;let s=this.readString(o);return this.module._free(o),s}finally{this.module._free(r),this.module._free(n);}}return this.log("getTextSelection: shim not available"),null}setTextSelection(e,t,r,n){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentSetTextSelection){this.module._lok_documentSetTextSelection(e,t,r,n);return}this.log("setTextSelection: shim not available");}getSelectionType(e){if(e===0)throw new Error("Invalid document pointer");return this.useShims&&this.module._lok_documentGetSelectionType?this.module._lok_documentGetSelectionType(e):(this.log("getSelectionType: shim not available"),0)}resetSelection(e){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentResetSelection){this.module._lok_documentResetSelection(e);return}this.log("resetSelection: shim not available");}postMouseEvent(e,t,r,n,o=1,s=1,i=0){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentPostMouseEvent){this.module._lok_documentPostMouseEvent(e,t,r,n,o,s,i);return}this.log("postMouseEvent: shim not available");}postKeyEvent(e,t,r,n){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentPostKeyEvent){this.module._lok_documentPostKeyEvent(e,t,r,n);return}this.log("postKeyEvent: shim not available");}postUnoCommand(e,t,r="{}",n=false){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentPostUnoCommand){let o=this.allocString(t),s=this.allocString(r);try{this.module._lok_documentPostUnoCommand(e,o,s,n?1:0);}finally{this.module._free(o),this.module._free(s);}return}this.log("postUnoCommand: shim not available");}getCommandValues(e,t){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentGetCommandValues){let r=this.allocString(t);try{let n=this.module._lok_documentGetCommandValues(e,r);if(n===0)return null;let o=this.readString(n);return this.module._free(n),o}finally{this.module._free(r);}}return this.log("getCommandValues: shim not available"),null}getPartPageRectangles(e){if(this.log(`getPartPageRectangles called with docPtr: ${e}`),e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentGetPartPageRectangles){this.log("getPartPageRectangles: using shim");let t=this.module._lok_documentGetPartPageRectangles(e);if(this.log(`getPartPageRectangles: resultPtr=${t}`),t===0)return null;let r=this.readString(t);return this.log(`getPartPageRectangles: result="${r?.slice(0,100)}..."`),this.module._free(t),r}return this.log("getPartPageRectangles: shim not available"),null}getPartInfo(e,t){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentGetPartInfo){let r=this.module._lok_documentGetPartInfo(e,t);if(r===0)return null;let n=this.readString(r);return this.module._free(r),n}return this.log("getPartInfo: shim not available"),null}getPartName(e,t){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentGetPartName){let r=this.module._lok_documentGetPartName(e,t);if(r===0)return null;let n=this.readString(r);return this.module._free(r),n}return this.log("getPartName: shim not available"),null}paste(e,t,r){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentPaste){let n=this.allocString(t),o,s;if(typeof r=="string"){let i=new TextEncoder().encode(r);s=i.length,o=this.module._malloc(s),this.HEAPU8.set(i,o);}else s=r.length,o=this.module._malloc(s),this.HEAPU8.set(r,o);try{return this.module._lok_documentPaste(e,n,o,s)!==0}finally{this.module._free(n),this.module._free(o);}}return this.log("paste: shim not available"),false}setClientZoom(e,t,r,n,o){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentSetClientZoom){this.module._lok_documentSetClientZoom(e,t,r,n,o);return}this.log("setClientZoom: shim not available");}setClientVisibleArea(e,t,r,n,o){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentSetClientVisibleArea){this.module._lok_documentSetClientVisibleArea(e,t,r,n,o);return}this.log("setClientVisibleArea: shim not available");}getA11yFocusedParagraph(e){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentGetA11yFocusedParagraph){let t=this.module._lok_documentGetA11yFocusedParagraph(e);if(t===0)return null;let r=this.readString(t);return this.module._free(t),r}return this.log("getA11yFocusedParagraph: shim not available"),null}getA11yCaretPosition(e){if(e===0)throw new Error("Invalid document pointer");return this.useShims&&this.module._lok_documentGetA11yCaretPosition?this.module._lok_documentGetA11yCaretPosition(e):(this.log("getA11yCaretPosition: shim not available"),-1)}setAccessibilityState(e,t,r){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentSetAccessibilityState){this.module._lok_documentSetAccessibilityState(e,t,r?1:0);return}this.log("setAccessibilityState: shim not available");}getDataArea(e,t){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentGetDataArea){let r=this.module._malloc(8),n=this.module._malloc(8);try{this.module._lok_documentGetDataArea(e,t,r,n);let o=this.HEAP32[r>>2]??0,s=this.HEAP32[n>>2]??0;return {col:o,row:s}}finally{this.module._free(r),this.module._free(n);}}return this.log("getDataArea: shim not available"),{col:0,row:0}}getEditMode(e){if(e===0)throw new Error("Invalid document pointer");return this.useShims&&this.module._lok_documentGetEditMode?this.module._lok_documentGetEditMode(e):(this.log("getEditMode: shim not available"),0)}setEditMode(e,t){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentSetEditMode){this.log(`setEditMode: setting mode to ${t}`),this.module._lok_documentSetEditMode(e,t);return}this.log("setEditMode: shim not available");}createView(e){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentCreateView){let t=this.module._lok_documentCreateView(e);return this.log(`createView: created view ${t}`),t}return this.log("createView: shim not available"),-1}createViewWithOptions(e,t){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentCreateViewWithOptions){let r=this.allocString(t);try{let n=this.module._lok_documentCreateViewWithOptions(e,r);return this.log(`createViewWithOptions: created view ${n}`),n}finally{this.module._free(r);}}return this.log("createViewWithOptions: shim not available"),-1}destroyView(e,t){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentDestroyView){this.log(`destroyView: destroying view ${t}`),this.module._lok_documentDestroyView(e,t);return}this.log("destroyView: shim not available");}setView(e,t){if(e===0)throw new Error("Invalid document pointer");if(this.useShims&&this.module._lok_documentSetView){this.log(`setView: setting active view to ${t}`),this.module._lok_documentSetView(e,t);return}this.log("setView: shim not available");}getView(e){if(e===0)throw new Error("Invalid document pointer");return this.useShims&&this.module._lok_documentGetView?this.module._lok_documentGetView(e):(this.log("getView: shim not available"),-1)}getViewsCount(e){if(e===0)throw new Error("Invalid document pointer");return this.useShims&&this.module._lok_documentGetViewsCount?this.module._lok_documentGetViewsCount(e):(this.log("getViewsCount: shim not available"),0)}enableSyncEvents(){this.useShims&&this.module._lok_enableSyncEvents?(this.module._lok_enableSyncEvents(),this.log("enableSyncEvents: Unipoll mode enabled")):this.log("enableSyncEvents: shim not available");}disableSyncEvents(){this.useShims&&this.module._lok_disableSyncEvents?(this.module._lok_disableSyncEvents(),this.log("disableSyncEvents: Unipoll mode disabled")):this.log("disableSyncEvents: shim not available");}registerCallback(e){if(e===0)throw new Error("Invalid document pointer");this.useShims&&this.module._lok_documentRegisterCallback?(this.module._lok_documentRegisterCallback(e),this.log("registerCallback: callback registered")):this.log("registerCallback: shim not available");}unregisterCallback(e){if(e===0)throw new Error("Invalid document pointer");this.useShims&&this.module._lok_documentUnregisterCallback?(this.module._lok_documentUnregisterCallback(e),this.log("unregisterCallback: callback unregistered")):this.log("unregisterCallback: shim not available");}hasCallbackEvents(){return this.useShims&&this.module._lok_hasCallbackEvents?this.module._lok_hasCallbackEvents()!==0:false}getCallbackEventCount(){return this.useShims&&this.module._lok_getCallbackEventCount?this.module._lok_getCallbackEventCount():0}pollCallback(){if(!this.useShims||!this.module._lok_pollCallback)return null;let e=4096,t=this.module._malloc(e),r=this.module._malloc(4);try{let n=this.module._lok_pollCallback(t,e,r);if(n===-1)return null;let o=this.module.HEAP32[r>>2]??0,s="";if(o>0){let i=Math.min(o,e-1),a=this.module.HEAPU8.slice(t,t+i);s=le.decode(a);}return {type:n,typeName:Oe(n),payload:s}}finally{this.module._free(t),this.module._free(r);}}pollAllCallbacks(){let e=[],t=this.pollCallback();for(;t!==null;)e.push(t),t=this.pollCallback();return e}clearCallbackQueue(){this.useShims&&this.module._lok_clearCallbackQueue&&(this.module._lok_clearCallbackQueue(),this.log("clearCallbackQueue: queue cleared"));}flushCallbacks(e){if(e===0)throw new Error("Invalid document pointer");let t=!!this.module._lok_flushCallbacks;this.log(`flushCallbacks: useShims=${this.useShims}, _lok_flushCallbacks exists=${t}`),this.useShims&&this.module._lok_flushCallbacks?(this.module._lok_flushCallbacks(e),this.log("flushCallbacks: callbacks flushed")):this.log("flushCallbacks: shim not available");}pollStateChanges(){let e=new Map,t=this.pollAllCallbacks();for(let r of t)if(r.type===8){let n=r.payload.indexOf("=");if(n!==-1){let o=r.payload.substring(0,n),s=r.payload.substring(n+1);e.set(o,s);}else e.set(r.payload,"");}return e}clickAndGetText(e,t,r){return this.postMouseEvent(e,0,t,r,1,1,0),this.postMouseEvent(e,1,t,r,1,1,0),this.getTextSelection(e,"text/plain;charset=utf-8")}doubleClickAndGetWord(e,t,r){return this.postMouseEvent(e,0,t,r,2,1,0),this.postMouseEvent(e,1,t,r,2,1,0),this.getTextSelection(e,"text/plain;charset=utf-8")}selectAll(e){this.postUnoCommand(e,".uno:SelectAll");}getAllText(e){this.log(`getAllText called with docPtr: ${e}`),this.selectAll(e);let t=this.getTextSelection(e,"text/plain;charset=utf-8");return this.log(`getAllText: text="${t?.slice(0,100)}..."`),this.resetSelection(e),t}parsePageRectangles(e){return e?e.split(";").filter(t=>t.trim()).map(t=>{let r=t.split(",").map(Number);return {x:r[0]??0,y:r[1]??0,width:r[2]??0,height:r[3]??0}}):[]}};var Y=class{module=null;lokBindings=null;initialized=false;initializing=false;options;corrupted=false;fsTracked=false;constructor(e={}){this.options={wasmPath:"./wasm",verbose:false,...e};}isCorruptionError(e){let t=e instanceof Error?e.message:e;return t.includes("memory access out of bounds")||t.includes("ComponentContext is not avail")||t.includes("unreachable")||t.includes("table index is out of bounds")||t.includes("null function")}async reinitialize(){if(this.options.verbose&&console.log("[LibreOfficeConverter] Reinitializing due to corruption..."),this.lokBindings){try{this.lokBindings.destroy();}catch{}this.lokBindings=null;}this.module=null,this.initialized=false,this.corrupted=false,await this.initialize();}async initializeWithModule(e){if(!this.initialized){if(this.initializing){for(;this.initializing;)await new Promise(t=>setTimeout(t,100));return}this.initializing=true;try{this.module=e,this.setupFileSystem(),this.initializeLibreOfficeKit(),this.initialized=!0,this.options.onReady?.();}catch(t){console.error("[LibreOfficeConverter] Initialization error:",t);let r=t instanceof S?t:new S("WASM_NOT_INITIALIZED",`Failed to initialize with module: ${String(t)}`);throw this.options.onError?.(r),r}finally{this.initializing=false;}}}async initialize(){if(!this.initialized){if(this.initializing){for(;this.initializing;)await new Promise(e=>setTimeout(e,100));return}this.initializing=true,this.emitProgress("loading",0,"Loading LibreOffice WASM module...");try{this.module=await this.loadModule(),this.emitProgress("initializing",50,"Setting up virtual filesystem..."),this.setupFileSystem(),this.emitProgress("initializing",60,"Initializing LibreOfficeKit..."),this.initializeLibreOfficeKit(),this.emitProgress("initializing",90,"LibreOfficeKit ready"),this.initialized=!0,this.emitProgress("complete",100,"LibreOffice ready"),this.options.onReady?.();}catch(e){console.error("[LibreOfficeConverter] Initialization error:",e);let t=e instanceof S?e:new S("WASM_NOT_INITIALIZED",`Failed to initialize WASM module: ${String(e)}`);throw this.options.onError?.(t),t}finally{this.initializing=false;}}}async loadModule(){let e=this.options.wasmPath||"./wasm",t=`${e}/soffice.js`,r={locateFile:s=>s.endsWith(".wasm")?`${e}/soffice.wasm`:s.endsWith(".data")?`${e}/soffice.data`:`${e}/${s}`,print:this.options.verbose?console.log:()=>{},printErr:this.options.verbose?console.error:()=>{}},n=document.createElement("script");n.src=t,await new Promise((s,i)=>{n.onload=()=>s(),n.onerror=()=>i(new Error(`Failed to load ${t}`)),document.head.appendChild(n);});let o=window.createSofficeModule;if(!o)throw new S("WASM_NOT_INITIALIZED","WASM module factory not found. Make sure soffice.js is loaded.");return new Promise((s,i)=>{let a={...r,onRuntimeInitialized:()=>{s(a);}};o(a).catch(i);})}setupFileSystem(){if(!this.module?.FS)throw new S("WASM_NOT_INITIALIZED","Filesystem not available");let e=this.module.FS,t=r=>{try{e.mkdir(r);}catch{}};t("/tmp"),t("/tmp/input"),t("/tmp/output");}initializeLibreOfficeKit(){if(!this.module)throw new S("WASM_NOT_INITIALIZED","Module not loaded");if(this.options.verbose&&this.module.FS){let e=this.module.FS;if(!this.fsTracked&&(this.fsTracked=true,e.trackingDelegate||(e.trackingDelegate={onOpen:r=>{console.log("[FS OPEN]",r);},onOpenFile:r=>{console.log("[FS OPEN FILE]",r);}}),typeof e.open=="function")){let r=e.open.bind(e);e.open=((n,o,s)=>{console.log("[FS OPEN CALL]",n);try{return r(n,o,s)}catch(i){throw i?.code==="ENOENT"&&console.log("[FS ENOENT]",n),i}});}let t=(r,n)=>{try{console.log(`[FS] ${r}:`,e.readdir(n));}catch(o){console.log(`[FS] ${r}: ERROR -`,o.message);}};t("ROOT","/"),t("PROGRAM DIR","/instdir/program"),t("SHARE DIR","/instdir/share"),t("REGISTRY DIR","/instdir/share/registry"),t("FILTER DIR","/instdir/share/filter"),t("CONFIG DIR","/instdir/share/config/soffice.cfg"),t("CONFIG FILTER","/instdir/share/config/soffice.cfg/filter"),t("IMPRESS MODULES","/instdir/share/config/soffice.cfg/modules/simpress");}this.lokBindings=new X(this.module,this.options.verbose);try{if(this.lokBindings.initialize("/instdir/program"),this.options.verbose){let e=this.lokBindings.getVersionInfo();e&&console.log("[LOK] Version:",e);}}catch(e){throw new S("WASM_NOT_INITIALIZED",`Failed to initialize LibreOfficeKit: ${String(e)}`)}}async convert(e,t,r="document"){if(this.corrupted&&await this.reinitialize(),!this.initialized||!this.module)throw new S("WASM_NOT_INITIALIZED","LibreOffice WASM not initialized. Call initialize() first.");let n=Date.now(),o=this.normalizeInput(e);if(o.length===0)throw new S("INVALID_INPUT","Empty document provided");let s=t.inputFormat||this.getExtensionFromFilename(r)||"docx",i=t.outputFormat;if(!q[i])throw new S("UNSUPPORTED_FORMAT",`Unsupported output format: ${i}`);if(!ee(s,i))throw new S("UNSUPPORTED_FORMAT",ie(s,i));let a=`/tmp/input/doc.${s}`,d=`/tmp/output/doc.${i}`;try{this.emitProgress("converting",10,"Writing input document..."),this.module.FS.writeFile(a,o),this.emitProgress("converting",30,"Converting document...");let h=await this.performConversion(a,d,t);this.emitProgress("complete",100,"Conversion complete");let u=`${this.getBasename(r)}.${i}`;return {data:h,mimeType:te[i],filename:u,duration:Date.now()-n}}catch(h){throw h instanceof Error&&this.isCorruptionError(h)&&(this.corrupted=true,this.options.verbose&&console.log("[LibreOfficeConverter] Corruption detected, will reinitialize on next convert")),h}finally{try{this.module?.FS.unlink(a);}catch{}try{this.module?.FS.unlink(d);}catch{}}}async performConversion(e,t,r){if(!this.module||!this.lokBindings)throw new S("WASM_NOT_INITIALIZED","Module not loaded");this.emitProgress("converting",40,"Loading document...");let n=0;try{let o=r.password?`,Password=${r.password}`:"";if(this.options.verbose)try{let a=this.module.FS.stat(e);console.log("[Convert] File exists before LOK load:",e,"size:",a.size);}catch(a){console.log("[Convert] File NOT found before LOK load:",e,a.message);}if(o?n=this.lokBindings.documentLoadWithOptions(e,o):n=this.lokBindings.documentLoad(e),n===0)throw new S("LOAD_FAILED","Failed to load document");this.emitProgress("converting",60,"Converting format...");let s=U[r.outputFormat],i=K[r.outputFormat]||"";if(r.outputFormat==="pdf"&&r.pdf){let a=[];if(r.pdf.pdfaLevel){let d={"PDF/A-1b":1,"PDF/A-2b":2,"PDF/A-3b":3};a.push(`SelectPdfVersion=${d[r.pdf.pdfaLevel]||0}`);}r.pdf.quality!==void 0&&a.push(`Quality=${r.pdf.quality}`),a.length>0&&(i=a.join(","));}if(["png","jpg","svg"].includes(r.outputFormat)&&r.image?.pageIndex!==void 0){let a=r.image.pageIndex+1;i?i+=`;PageRange=${a}-${a}`:i=`PageRange=${a}-${a}`;}this.emitProgress("converting",70,"Saving document..."),this.lokBindings.documentSaveAs(n,t,s,i),this.emitProgress("converting",90,"Reading output...");try{let a=this.module.FS.readFile(t);if(a.length===0)throw new S("CONVERSION_FAILED","Conversion produced empty output");return a}catch(a){throw new S("CONVERSION_FAILED",`Failed to read converted file: ${String(a)}`)}}catch(o){throw o instanceof S?o:new S("CONVERSION_FAILED",`Conversion failed: ${String(o)}`)}finally{if(n!==0&&this.lokBindings)try{this.lokBindings.documentDestroy(n);}catch{}}}async renderPagePreviews(e,t,r={}){if(!this.initialized||!this.module||!this.lokBindings)throw new S("WASM_NOT_INITIALIZED","Converter not initialized");let n=this.normalizeInput(e),o=(t.inputFormat||"docx").toLowerCase(),s=r.width??256,i=r.height??0,a=r.pageIndices??[],d=`/tmp/preview/doc.${o}`,h=this.module.FS;try{try{h.mkdir("/tmp/preview");}catch{}h.writeFile(d,n);let m=this.lokBindings.documentLoad(d);if(m===0)throw new S("LOAD_FAILED","Failed to load document for preview");try{let u=this.lokBindings.documentGetParts(m);this.options.verbose&&console.log(`[Preview] Document has ${u} pages/parts`);let g=a.length>0?a.filter(p=>p>=0&&pO),f=[],P=r.editMode??!1;for(let p of g){this.options.verbose&&console.log(`[Preview] Rendering page ${p+1}/${u}`);let O=this.lokBindings.renderPage(m,p,s,i,P);f.push({page:p,data:O.data,width:O.width,height:O.height});}return f}finally{this.lokBindings.documentDestroy(m);}}finally{try{h.unlink(d);}catch{}try{h.rmdir("/tmp/preview");}catch{}}}async renderPageFullQuality(e,t,r,n={}){if(!this.initialized||!this.module||!this.lokBindings)throw new S("WASM_NOT_INITIALIZED","Converter not initialized");let o=this.normalizeInput(e),s=(t.inputFormat||"docx").toLowerCase(),i=n.dpi??150,a=n.maxDimension,d=`/tmp/fullquality/doc.${s}`,h=this.module.FS;try{try{h.mkdir("/tmp/fullquality");}catch{}h.writeFile(d,o);let m=this.lokBindings.documentLoad(d);if(m===0)throw new S("LOAD_FAILED","Failed to load document for full quality render");try{let u=this.lokBindings.documentGetParts(m);if(r<0||r>=u)throw new S("CONVERSION_FAILED",`Page index ${r} out of range (0-${u-1})`);this.options.verbose&&console.log(`[FullQuality] Rendering page ${r+1}/${u} at ${i} DPI`);let g=n.editMode??!1,f=this.lokBindings.renderPageFullQuality(m,r,i,a,g);return {page:r,data:f.data,width:f.width,height:f.height,dpi:f.dpi}}finally{this.lokBindings.documentDestroy(m);}}finally{try{h.unlink(d);}catch{}try{h.rmdir("/tmp/fullquality");}catch{}}}async getPageCount(e,t){if(!this.initialized||!this.module||!this.lokBindings)throw new S("WASM_NOT_INITIALIZED","Converter not initialized");let r=this.normalizeInput(e),o=`/tmp/pagecount/doc.${(t.inputFormat||"docx").toLowerCase()}`,s=this.module.FS;try{try{s.mkdir("/tmp/pagecount");}catch{}s.writeFile(o,r);let i=this.lokBindings.documentLoad(o);if(i===0)throw new S("LOAD_FAILED","Failed to load document");try{return this.lokBindings.documentGetParts(i)}finally{this.lokBindings.documentDestroy(i);}}finally{try{s.unlink(o);}catch{}try{s.rmdir("/tmp/pagecount");}catch{}}}async getDocumentInfo(e,t){if(!this.initialized||!this.module||!this.lokBindings)throw new S("WASM_NOT_INITIALIZED","Converter not initialized");let r=this.normalizeInput(e),o=`/tmp/docinfo/doc.${(t.inputFormat||"docx").toLowerCase()}`,s=this.module.FS;try{try{s.mkdir("/tmp/docinfo");}catch{}s.writeFile(o,r);let i=this.lokBindings.documentLoad(o);if(i===0)throw new S("LOAD_FAILED","Failed to load document");try{let a=this.lokBindings.documentGetDocumentType(i),d=this.lokBindings.documentGetParts(i),h=oe(a),m={0:"Text Document",1:"Spreadsheet",2:"Presentation",3:"Drawing",4:"Other"};return {documentType:a,documentTypeName:m[a]||"Unknown",validOutputFormats:h,pageCount:d}}finally{this.lokBindings.documentDestroy(i);}}finally{try{s.unlink(o);}catch{}try{s.rmdir("/tmp/docinfo");}catch{}}}async getDocumentText(e,t){if(!this.initialized||!this.module||!this.lokBindings)throw new S("WASM_NOT_INITIALIZED","Converter not initialized");let r=this.normalizeInput(e),n=t.inputFormat?.toLowerCase();if(!n)throw new S("INVALID_INPUT","Input format is required");let o=`/tmp/inspect/doc.${n}`,s=this.module.FS;try{try{s.mkdir("/tmp/inspect");}catch{}s.writeFile(o,r);let i=this.lokBindings.documentLoad(o);if(i===0)throw new S("LOAD_FAILED","Failed to load document");try{return this.lokBindings.getAllText(i)}finally{this.lokBindings.documentDestroy(i);}}finally{try{s.unlink(o);}catch{}try{s.rmdir("/tmp/inspect");}catch{}}}async getPageNames(e,t){if(!this.initialized||!this.module||!this.lokBindings)throw new S("WASM_NOT_INITIALIZED","Converter not initialized");let r=this.normalizeInput(e),n=t.inputFormat?.toLowerCase();if(!n)throw new S("INVALID_INPUT","Input format is required");let o=`/tmp/names/doc.${n}`,s=this.module.FS;try{try{s.mkdir("/tmp/names");}catch{}s.writeFile(o,r);let i=this.lokBindings.documentLoad(o);if(i===0)throw new S("LOAD_FAILED","Failed to load document");try{let a=this.lokBindings.documentGetParts(i),d=[];for(let h=0;h1&&t.pop()?.toLowerCase()||null}getBasename(e){let t=e.lastIndexOf(".");return t>0?e.substring(0,t):e}emitProgress(e,t,r){this.options.onProgress?.({phase:e,percent:t,message:r});}};var de={"download-wasm":50,"download-data":30,compile:5,filesystem:7,"lok-init":7,ready:1,starting:0,loading:0,initializing:0,converting:0,complete:0},x={"download-wasm":0,"download-data":0,compile:0,filesystem:0,"lok-init":0,ready:0,starting:0,loading:0,initializing:0,converting:0,complete:0},he=0,Z=0;function me(){let l=0;for(let t of Object.keys(x))l+=x[t];let e=Math.min(100,Math.round(l));return e>Z&&(Z=e),Z}function Q(l){return `${(l/1048576).toFixed(1)} MB`}function ce(l,e,t){let r=de[l],n=t>0?e/t:0,o=r*n;o>x[l]&&(x[l]=o);let s=l==="download-wasm"?`Downloading WebAssembly... ${Q(e)} / ${Q(t)}`:`Downloading filesystem... ${Q(e)} / ${Q(t)}`;pe({percent:me(),message:s,phase:l,bytesLoaded:e,bytesTotal:t});}function $(l,e){let t=de[l];t>x[l]&&(x[l]=t),pe({percent:me(),message:e,phase:l});}function pe(l){self.postMessage({type:"progress",id:he,progress:l});}function ke(){let l=self.fetch;self.fetch=async function(r,n){let o=typeof r=="string"?r:r instanceof URL?r.href:r.url,s=null;o.includes("soffice.wasm")?(s="download-wasm",console.log("[Worker] Starting fetch download: soffice.wasm")):o.includes("soffice.data")&&(s="download-data",console.log("[Worker] Starting fetch download: soffice.data"));let i=await l(r,n);if(!s)return i;if(s==="download-wasm")return console.log("[Worker] Returning original response for soffice.wasm (streaming compile requires raw Response)"),i;let a=i.headers.get("Content-Length"),d=a?parseInt(a,10):0;if(!d||!i.body)return console.log(`[Worker] No content-length for ${o}, skipping progress tracking`),i;let h=i.body.getReader(),m=0,u=new ReadableStream({async start(g){for(;;){let{done:f,value:P}=await h.read();if(f){console.log("[Worker] Finished fetch download: soffice.data"),g.close();break}m+=P.length,ce(s,m,d),g.enqueue(P);}}});return new Response(u,{headers:i.headers,status:i.status,statusText:i.statusText})},console.log("[Worker] Installed progress-tracking fetch interceptor");let e=self.XMLHttpRequest,t=function(){let r=new e,n="",o=r.open.bind(r);r.open=function(i,a,d,h,m){return n=String(a),o(i,a,d??true,h,m)};let s=r.send.bind(r);return r.send=function(i){let a=null;if(n.includes("soffice.wasm")?(a="download-wasm",console.log("[Worker] Starting XHR download: soffice.wasm")):n.includes("soffice.data")&&(a="download-data",console.log("[Worker] Starting XHR download: soffice.data")),a){let d=a;r.addEventListener("progress",h=>{h.lengthComputable&&ce(d,h.loaded,h.total);}),r.addEventListener("load",()=>{console.log(`[Worker] Finished XHR download: ${d==="download-wasm"?"soffice.wasm":"soffice.data"}`);});}return s(i)},r};Object.defineProperty(t,"prototype",{value:e.prototype,writable:false}),self.XMLHttpRequest=t,console.log("[Worker] Installed progress-tracking XHR interceptor");}var E=null,c=null,D=null,w=false,v=null,W=new Map,be=0;function Ce(l){let e=0,t=Math.max(1,Math.floor(l.length/1e3));for(let r=0;r{let d;return i.endsWith(".wasm")?d=t:i.endsWith(".data")?d=r:i.includes(".worker.")?d=n:d=`${e.substring(0,e.lastIndexOf("/")+1)}${i}`,console.log("[Worker] locateFile called:",i,"scriptDir:",a,"-> result:",d),d},print:console.log,printErr:console.error},importScripts(e),$("compile","Compiling WebAssembly module..."),await new Promise((i,a)=>{let d=()=>{if(self.Module&&self.Module.calledRun)i();else if(self.Module?.onRuntimeInitialized){let h=self.Module.onRuntimeInitialized;self.Module.onRuntimeInitialized=()=>{h?.(),i();};}else self.Module&&(self.Module.onRuntimeInitialized=i);setTimeout(()=>a(new Error("WASM initialization timeout")),12e4);};self.Module&&self.Module.calledRun?i():d();}),E=self.Module,$("filesystem","Setting up filesystem...");try{let i=E;i.ENV?(i.ENV.SAL_LOG="+ALL",i.ENV.MAX_CONCURRENCY="1",console.log("[Worker] Set SAL_LOG to +ALL")):console.log("[Worker] ENV not available");}catch(i){console.log("[Worker] Could not set SAL_LOG:",i);}let s=E.FS;if(o){let i=s.open.bind(s);s.open=(a,d,h)=>{console.log("[FS OPEN CALL]",a);try{return i(a,d,h)}catch(m){throw m?.code==="ENOENT"&&console.log("[FS ENOENT]",a),m}};}try{s.mkdir("/tmp");}catch{}try{s.mkdir("/tmp/input");}catch{}try{s.mkdir("/tmp/output");}catch{}if($("lok-init","Initializing LibreOfficeKit..."),D=new Y({verbose:o}),await D.initializeWithModule(E),c=D.getLokBindings(),!c)throw new Error("Failed to get LOK bindings from converter");c.enableSyncEvents(),console.log("[LOK Worker] Enabled synchronous event dispatch (Unipoll mode)"),w=!0,$("ready","Ready"),y({type:"ready",id:l.id});}catch(s){y({type:"error",id:l.id,error:s instanceof Error?s.message:String(s)});}}var Le=["png","jpg","jpeg","svg"];function Re(l){if(!w||!E||!c){y({type:"error",id:l.id,error:"Worker not initialized"});return}let{inputData:e,inputExt:t,outputFormat:r,filterOptions:n,password:o}=l;if(!e||!r){y({type:"error",id:l.id,error:"Missing input data or output format"});return}let s=Le.includes(r.toLowerCase()),i=`/tmp/input/doc.${t||"docx"}`,a=`/tmp/output/doc.${r}`,d=0,h=[];try{if(R(l.id,10,"Writing input file..."),E.FS.writeFile(i,e),R(l.id,30,"Loading document..."),o?d=c.documentLoadWithOptions(i,`,Password=${o}`):d=c.documentLoad(i),d===0){let g=c.getError();throw new Error(g||"Failed to load document")}let m=c.documentGetParts(d),u=c.documentGetDocumentType(d);if(s&&m>1){R(l.id,40,`Exporting ${m} pages as ${r.toUpperCase()}...`);let g=U[r],f=n||K[r]||"",P=[],{width:p,height:O}=c.documentGetDocumentSize(d),_=O/p,k=1024,N=Math.round(k*_);for(let b=0;b0){let L=new Uint8Array(T.length);L.set(T),P.push({name:`page_${b+1}.${r}`,data:L});}else console.warn(`[Worker] Page ${b+1} export produced empty file`);}R(l.id,85,"Creating ZIP archive...");let M=ve(P);R(l.id,100,"Complete"),y({type:"result",id:l.id,data:M});}else {R(l.id,50,"Converting...");let g=U[r],f=n||K[r]||"";R(l.id,70,"Saving..."),c.documentSaveAs(d,a,g,f),h.push(a),R(l.id,90,"Reading output...");let P=E.FS.readFile(a);if(P.length===0)throw new Error("Conversion produced empty output");let p=new Uint8Array(P.length);p.set(P),R(l.id,100,"Complete"),y({type:"result",id:l.id,data:p});}}catch(m){y({type:"error",id:l.id,error:m instanceof Error?m.message:String(m)});}finally{if(d!==0)try{c.documentDestroy(d);}catch{}try{E.FS.unlink(i);}catch{}for(let m of h)try{E.FS.unlink(m);}catch{}}}function ve(l){let e=[],t=[],r=0;for(let m of l){let u=new TextEncoder().encode(m.name),g=new Uint8Array(30+u.length),f=new DataView(g.buffer);f.setUint32(0,67324752,true),f.setUint16(4,20,true),f.setUint16(6,0,true),f.setUint16(8,0,true),f.setUint16(10,0,true),f.setUint16(12,0,true),f.setUint32(14,ue(m.data),true),f.setUint32(18,m.data.length,true),f.setUint32(22,m.data.length,true),f.setUint16(26,u.length,true),f.setUint16(28,0,true),g.set(u,30),e.push(g),e.push(m.data);let P=new Uint8Array(46+u.length),p=new DataView(P.buffer);p.setUint32(0,33639248,true),p.setUint16(4,20,true),p.setUint16(6,20,true),p.setUint16(8,0,true),p.setUint16(10,0,true),p.setUint16(12,0,true),p.setUint16(14,0,true),p.setUint32(16,ue(m.data),true),p.setUint32(20,m.data.length,true),p.setUint32(24,m.data.length,true),p.setUint16(28,u.length,true),p.setUint16(30,0,true),p.setUint16(32,0,true),p.setUint16(34,0,true),p.setUint16(36,0,true),p.setUint32(38,0,true),p.setUint32(42,r,true),P.set(u,46),t.push(P),r+=g.length+m.data.length;}let n=r,o=0;for(let m of t)e.push(m),o+=m.length;let s=new Uint8Array(22),i=new DataView(s.buffer);i.setUint32(0,101010256,true),i.setUint16(4,0,true),i.setUint16(6,0,true),i.setUint16(8,l.length,true),i.setUint16(10,l.length,true),i.setUint32(12,o,true),i.setUint32(16,n,true),i.setUint16(20,0,true),e.push(s);let a=e.reduce((m,u)=>m+u.length,0),d=new Uint8Array(a),h=0;for(let m of e)d.set(m,h),h+=m.length;return d}function ue(l){let e=4294967295;for(let t=0;t>>1^(e&1?3988292384:0);}return (e^4294967295)>>>0}async function Ae(l){if(!w||!E||!c){y({type:"error",id:l.id,error:"Worker not initialized"});return}let{inputData:e,inputExt:t}=l;if(!e){y({type:"error",id:l.id,error:"Missing input data"});return}try{let{pageCount:r}=F(e,t||"docx");y({type:"pageCount",id:l.id,pageCount:r});}catch(r){y({type:"error",id:l.id,error:r instanceof Error?r.message:String(r)}),A();}}async function Ie(l){if(!w||!E||!c){y({type:"error",id:l.id,error:"Worker not initialized"});return}let{inputData:e,inputExt:t,maxWidth:r=256}=l;if(!e){y({type:"error",id:l.id,error:"Missing input data"});return}try{R(l.id,10,"Loading document for preview...");let{docPtr:n,pageCount:o}=F(e,t||"docx");R(l.id,20,`Rendering ${o} pages...`);let s=[];for(let a=0;aa.data.buffer);self.postMessage({type:"previews",id:l.id,previews:s},i);}catch(n){y({type:"error",id:l.id,error:n instanceof Error?n.message:String(n)}),A();}}async function xe(l){if(!w||!E||!c){y({type:"error",id:l.id,error:"Worker not initialized"});return}let{inputData:e,inputExt:t,maxWidth:r=256,pageIndex:n=0}=l;if(!e){y({type:"error",id:l.id,error:"Missing input data"});return}let o=-1,s=0;try{let i=F(e,t||"docx");s=i.docPtr;let a=i.pageCount;if(n<0||n>=a)throw new Error(`Page index ${n} out of range (0-${a-1})`);let d=c.documentGetDocumentType(s);console.log(`[Worker] handleRenderSinglePage: ${["TEXT","SPREADSHEET","PRESENTATION","DRAWING"][d]||"UNKNOWN"} document - creating view for rendering`),o=c.createView(s),o>=0&&(c.setView(s,o),console.log(`[Worker] handleRenderSinglePage: Created and set view ${o}`)),console.log(`[Worker] handleRenderSinglePage: calling renderPage for page ${n} at maxWidth=${r}...`);let m=c.renderPage(s,n,r);console.log(`[Worker] handleRenderSinglePage: renderPage returned ${m.data.length} bytes (${m.width}x${m.height})`);let u=new Uint8Array(m.data.length);u.set(m.data);let g={page:n+1,data:u,width:m.width,height:m.height};if(o>=0&&s!==0){try{c.destroyView(s,o);}catch{}console.log(`[Worker] handleRenderSinglePage: Destroyed view ${o}`);}self.postMessage({type:"singlePagePreview",id:l.id,preview:g},[u.buffer]);}catch(i){if(o>=0&&s!==0){try{c.destroyView(s,o);}catch{}console.log(`[Worker] handleRenderSinglePage: Destroyed view ${o} (on error)`);}let a=i instanceof Error?String(i.message):String(i);y({type:"error",id:l.id,error:a}),A();}}async function Fe(l){if(!w||!E||!c){y({type:"error",id:l.id,error:"Worker not initialized"});return}let{inputData:e,inputExt:t,maxWidth:r=256,pageIndex:n=0}=l;if(!e){y({type:"error",id:l.id,error:"Missing input data"});return}let o=`/tmp/output/page_${n}.png`;try{let{docPtr:s,pageCount:i}=F(e,t||"pdf"),a=c.documentGetDocumentType(s);if(n<0||n>=i)throw new Error(`Page index ${n} out of range (0-${i-1})`);(a===2||a===3)&&c.documentSetPart(s,n);let{width:d,height:h}=c.documentGetDocumentSize(s),m=h/d,u=Math.min(r,d),g=Math.round(u*m),f=`PixelWidth=${u};PixelHeight=${g}`;a===0&&(f+=`;PageRange=${n+1}-${n+1}`),c.documentSaveAs(s,o,"png",f);let P=E.FS.readFile(o);if(P.length===0)throw new Error("PNG export produced empty output");let p=new Uint8Array(P.length);p.set(P);let O={page:n+1,data:p,width:u,height:g,format:"png"};self.postMessage({type:"singlePagePreview",id:l.id,preview:O,isPng:!0},[p.buffer]);try{E.FS.unlink(o);}catch{}}catch(s){y({type:"error",id:l.id,error:s instanceof Error?s.message:String(s)}),A();try{E.FS.unlink(o);}catch{}}}async function De(l){if(!w||!E||!c){y({type:"error",id:l.id,error:"Worker not initialized"});return}let{inputData:e,inputExt:t,pageIndex:r=0,dpi:n=150,maxDimension:o,editMode:s=false}=l;if(!e){y({type:"error",id:l.id,error:"Missing input data"});return}let i=-1,a=0;try{let d=F(e,t||"docx");a=d.docPtr;let h=d.pageCount;if(r<0||r>=h)throw new Error(`Page index ${r} out of range (0-${h-1})`);let m=c.documentGetDocumentType(a);console.log(`[Worker] handleRenderPageFullQuality: ${["TEXT","SPREADSHEET","PRESENTATION","DRAWING"][m]||"UNKNOWN"} document at ${n} DPI, editMode=${s}`),i=c.createView(a),i>=0&&(c.setView(a,i),console.log(`[Worker] handleRenderPageFullQuality: Created and set view ${i}`));let g=c.renderPageFullQuality(a,r,n,o,s);console.log(`[Worker] handleRenderPageFullQuality: rendered ${g.data.length} bytes (${g.width}x${g.height} at ${g.dpi} DPI)`);let f=new Uint8Array(g.data.length);f.set(g.data);let P={page:r+1,data:f,width:g.width,height:g.height,dpi:g.dpi};if(i>=0&&a!==0)try{c.destroyView(a,i);}catch{}self.postMessage({type:"fullQualityPagePreview",id:l.id,preview:P},[f.buffer]);}catch(d){if(i>=0&&a!==0)try{c.destroyView(a,i);}catch{}let h=d instanceof Error?String(d.message):String(d);y({type:"error",id:l.id,error:h}),A();}}async function We(l){if(!w||!E||!c){y({type:"error",id:l.id,error:"Worker not initialized"});return}let{inputData:e,inputExt:t}=l;if(!e){y({type:"error",id:l.id,error:"Missing input data"});return}try{let{docPtr:r,pageCount:n}=F(e,t||"docx"),o=c.documentGetDocumentType(r),s={0:["pdf","docx","doc","odt","rtf","txt","html","png","jpg","svg"],1:["pdf","xlsx","xls","ods","csv","html","png","jpg","svg"],2:["pdf","pptx","ppt","odp","png","jpg","svg","html"],3:["pdf","png","jpg","svg","html"],4:["pdf"]},a={documentType:o,documentTypeName:{0:"Text Document",1:"Spreadsheet",2:"Presentation",3:"Drawing",4:"Other"}[o]||"Unknown",validOutputFormats:s[o]||["pdf"],pageCount:n};y({type:"documentInfo",id:l.id,documentInfo:a});}catch(r){y({type:"error",id:l.id,error:r instanceof Error?r.message:String(r)}),A();}}async function Ne(l){if(console.log("[LOK Worker] handleGetLokInfo called"),!w||!E||!c){y({type:"error",id:l.id,error:"Worker not initialized"});return}let{inputData:e,inputExt:t}=l;if(!e){y({type:"error",id:l.id,error:"Missing input data"});return}try{console.log("[LOK Worker] Getting or loading document...");let{docPtr:r}=F(e,t||"docx");console.log(`[LOK Worker] Got docPtr: ${r}`),console.log("[LOK Worker] Calling LOK methods...");let n=c.getPartPageRectangles(r);console.log(`[LOK Worker] pageRectangles: ${n}`);let o=c.documentGetDocumentSize(r);console.log(`[LOK Worker] documentSize: ${o.width}x${o.height}`);let s=c.getPartInfo(r,0);console.log(`[LOK Worker] partInfo: ${s}`);let i=c.getA11yFocusedParagraph(r);console.log(`[LOK Worker] a11yFocusedParagraph: ${i}`);let a=c.getA11yCaretPosition(r);console.log(`[LOK Worker] a11yCaretPosition: ${a}`);let d=c.getEditMode(r);console.log(`[LOK Worker] editMode (initial): ${d}`);let h=null,m=-1;m=c.getView(r),console.log(`[LOK Worker] Got existing view: ${m}`),m>=0&&(c.setView(r,m),console.log(`[LOK Worker] Set active view to ${m}`));let u=c.createView(r);console.log(`[LOK Worker] Created new view: ${u}`),u>=0&&(c.setView(r,u),console.log(`[LOK Worker] Switched to new view: ${u}`)),c.setEditMode(r,1),d=c.getEditMode(r),console.log(`[LOK Worker] editMode (after setEditMode): ${d}`),h=c.getAllText(r),console.log(`[LOK Worker] allText: ${h?.slice(0,100)||"null"}`),u>=0&&(c.destroyView(r,u),console.log(`[LOK Worker] Destroyed view: ${u}`));let g=null;if(s)try{g=JSON.parse(s);}catch{console.warn("[LOK Worker] Failed to parse partInfo JSON:",s);}let f=null;if(i)try{f=JSON.parse(i);}catch{console.warn("[LOK Worker] Failed to parse a11yFocusedParagraph JSON:",i);}let P={pageRectangles:n,documentSize:o,partInfo:g,a11yFocusedParagraph:f,a11yCaretPosition:a,editMode:d,allText:h};console.log("[LOK Worker] Posting lokInfo response"),y({type:"lokInfo",id:l.id,lokInfo:P});}catch(r){console.error("[LOK Worker] Error in handleGetLokInfo:",r),y({type:"error",id:l.id,error:r instanceof Error?r.message:String(r)}),A();}}async function Ue(l){if(console.log("[LOK Worker] handleEditText called"),!w||!E||!c){y({type:"error",id:l.id,error:"Worker not initialized"});return}let{inputData:e,inputExt:t,findText:r,replaceText:n,insertText:o}=l;if(!e){y({type:"error",id:l.id,error:"Missing input data"});return}A();let s=`/tmp/input/edit_doc.${t||"docx"}`,i=`/tmp/output/edited_doc.${t||"docx"}`,a=0,d=-1;try{if(console.log("[LOK Worker] Writing input file..."),E.FS.writeFile(s,e),console.log("[LOK Worker] Loading document for editing..."),a=c.documentLoad(s),a===0){let p=c.getError();throw new Error(p||"Failed to load document")}console.log(`[LOK Worker] Document loaded, docPtr=${a}`),c.documentInitializeForRendering(a),console.log("[LOK Worker] Document initialized for rendering"),d=c.getView(a),console.log(`[LOK Worker] Got existing view: ${d}`),d>=0&&(c.setView(a,d),console.log(`[LOK Worker] Set active view to ${d}`));let h=c.createView(a);console.log(`[LOK Worker] Created new view: ${h}`),h>=0&&(c.setView(a,h),console.log(`[LOK Worker] Switched to new view: ${h}`),d=h),c.setEditMode(a,1);let m=c.getEditMode(a);console.log(`[LOK Worker] Edit mode after setEditMode(1): ${m}`);let u="";if(r&&n!==void 0){console.log(`[LOK Worker] Attempting find/replace: "${r}" -> "${n}"`);let p=JSON.stringify({"SearchItem.SearchString":{type:"string",value:r},"SearchItem.ReplaceString":{type:"string",value:n},"SearchItem.Command":{type:"unsigned short",value:"3"}});try{c.postUnoCommand(a,".uno:ExecuteSearch",p),u=`Attempted replace all "${r}" with "${n}"`,console.log(`[LOK Worker] ${u}`);}catch(O){console.error("[LOK Worker] ExecuteSearch threw:",O),u=`ExecuteSearch failed: ${String(O)}`;}}else if(o){console.log(`[LOK Worker] Attempting to insert text: "${o}"`);let p=[];try{console.log("[LOK Worker] Clicking in document to establish focus..."),c.postMouseEvent(a,0,1e3,1e3,1,1,0),c.postMouseEvent(a,1,1e3,1e3,1,1,0),console.log("[LOK Worker] Posted mouse events for focus"),p.push("mouseEvents:ok");}catch(_){console.error("[LOK Worker] postMouseEvent threw:",_),p.push("mouseEvents:err");}try{c.postUnoCommand(a,".uno:GoToEndOfDoc"),console.log("[LOK Worker] Posted GoToEndOfDoc"),p.push("GoToEndOfDoc:ok");}catch(_){console.error("[LOK Worker] GoToEndOfDoc threw:",_),p.push("GoToEndOfDoc:err");}let O=!1;try{console.log("[LOK Worker] Trying paste() with text/plain..."),O=c.paste(a,"text/plain;charset=utf-8",o),console.log(`[LOK Worker] paste() returned: ${O}`),p.push(`paste:${O}`);}catch(_){console.error("[LOK Worker] paste() threw:",_),p.push("paste:err");}try{let _=JSON.stringify({Text:{type:"string",value:o}});c.postUnoCommand(a,".uno:InsertText",_),console.log("[LOK Worker] Posted InsertText"),p.push("InsertText:ok");}catch(_){console.error("[LOK Worker] InsertText threw:",_),p.push("InsertText:err");}try{console.log("[LOK Worker] Now trying postKeyEvent for each character...");for(let _=0;_=0)try{c.destroyView(a,d);}catch{}try{c.documentDestroy(a);}catch{}}if(E){try{E.FS.unlink(s);}catch{}try{E.FS.unlink(i);}catch{}}}}async function Ke(l){if(console.log("[LOK Worker] handleRenderPageRectangles called"),!w||!E||!c){y({type:"error",id:l.id,error:"Worker not initialized"});return}let{inputData:e,inputExt:t,maxWidth:r=256}=l;if(!e){y({type:"error",id:l.id,error:"Missing input data"});return}try{let{docPtr:n}=F(e,t||"docx");c.documentInitializeForRendering(n);let o=c.getPartPageRectangles(n);if(console.log(`[LOK Worker] Page rectangles string: ${o?.slice(0,100)||"null"}...`),!o||o.length===0){y({type:"pageRectangles",id:l.id,pageRectangles:[]});return}let s=c.parsePageRectangles(o);console.log(`[LOK Worker] Parsed ${s.length} page rectangles`);let i=[],a=[];for(let d=0;d=0&&c.setView(o,s);let a=c.createView(o);console.log(`[LOK Worker] Created new view: ${a}`),a>=0&&(c.setView(o,a),s=a),c.setEditMode(o,1);let d=c.getEditMode(o);console.log(`[LOK Worker] Edit mode: ${d}`),c.registerCallback(o),c.clearCallbackQueue(),console.log("[LOK Worker] Callback registered for STATE_CHANGED events");try{c.postMouseEvent(o,0,1e3,1e3,1,1,0),c.postMouseEvent(o,1,1e3,1e3,1,1,0),i.push({operation:"establishFocus",success:!0,result:"Mouse click events sent"});}catch(u){i.push({operation:"establishFocus",success:!1,error:String(u)});}console.log("[LOK Worker] Testing SelectAll + getTextSelection...");try{c.postUnoCommand(o,".uno:SelectAll");let u=c.getTextSelection(o,"text/plain;charset=utf-8"),g=u?.length||0;console.log(`[LOK Worker] SelectAll result: ${g} chars, preview: "${u?.slice(0,100)}..."`),i.push({operation:"SelectAll+getTextSelection",success:g>0,result:{textLength:g,preview:u?.slice(0,200)}});}catch(u){console.error("[LOK Worker] SelectAll error:",u),i.push({operation:"SelectAll+getTextSelection",success:!1,error:String(u)});}console.log("[LOK Worker] Testing getSelectionType...");try{let u=c.getSelectionType(o);console.log(`[LOK Worker] Selection type: ${u}`),i.push({operation:"getSelectionType",success:!0,result:{selectionType:u,meaning:u===0?"NONE":u===1?"TEXT":u===2?"CELL":"UNKNOWN"}});}catch(u){console.error("[LOK Worker] getSelectionType error:",u),i.push({operation:"getSelectionType",success:!1,error:String(u)});}console.log("[LOK Worker] Testing resetSelection...");try{c.resetSelection(o);let u=c.getSelectionType(o);console.log(`[LOK Worker] Selection type after reset: ${u}`),i.push({operation:"resetSelection",success:!0,result:{selectionTypeAfterReset:u}});}catch(u){console.error("[LOK Worker] resetSelection error:",u),i.push({operation:"resetSelection",success:!1,error:String(u)});}console.log("[LOK Worker] Testing GoToStartOfDoc + selection + Delete...");try{c.postUnoCommand(o,".uno:GoToStartOfDoc"),console.log("[LOK Worker] Sent GoToStartOfDoc"),c.postUnoCommand(o,".uno:WordRightSel"),console.log("[LOK Worker] Sent WordRightSel");let u=c.getTextSelection(o,"text/plain;charset=utf-8");console.log(`[LOK Worker] Selected text before delete: "${u}"`),c.postUnoCommand(o,".uno:Delete"),console.log("[LOK Worker] Sent Delete"),i.push({operation:"SelectWord+Delete",success:!0,result:{deletedText:u}});}catch(u){console.error("[LOK Worker] SelectWord+Delete error:",u),i.push({operation:"SelectWord+Delete",success:!1,error:String(u)});}console.log("[LOK Worker] Testing Undo...");try{c.postUnoCommand(o,".uno:Undo"),console.log("[LOK Worker] Sent Undo"),c.postUnoCommand(o,".uno:SelectAll");let u=c.getTextSelection(o,"text/plain;charset=utf-8");console.log(`[LOK Worker] Text after Undo: ${u?.length} chars`),i.push({operation:"Undo",success:!0,result:{textLengthAfterUndo:u?.length||0}});}catch(u){console.error("[LOK Worker] Undo error:",u),i.push({operation:"Undo",success:!1,error:String(u)});}console.log("[LOK Worker] Testing Redo...");try{c.postUnoCommand(o,".uno:Redo"),console.log("[LOK Worker] Sent Redo"),c.postUnoCommand(o,".uno:SelectAll");let u=c.getTextSelection(o,"text/plain;charset=utf-8");console.log(`[LOK Worker] Text after Redo: ${u?.length} chars`),i.push({operation:"Redo",success:!0,result:{textLengthAfterRedo:u?.length||0}});}catch(u){console.error("[LOK Worker] Redo error:",u),i.push({operation:"Redo",success:!1,error:String(u)});}console.log("[LOK Worker] Testing Bold formatting...");try{c.postUnoCommand(o,".uno:Undo"),c.postUnoCommand(o,".uno:GoToStartOfDoc"),c.postUnoCommand(o,".uno:WordRightSel");let u=c.getTextSelection(o,"text/plain;charset=utf-8");console.log(`[LOK Worker] Selected for bold: "${u}"`),c.postUnoCommand(o,".uno:Bold"),console.log("[LOK Worker] Sent Bold");let g=c.getCommandValues(o,".uno:Bold");console.log(`[LOK Worker] Bold state: ${g}`),i.push({operation:"Bold",success:!0,result:{selectedText:u,boldState:g}});}catch(u){console.error("[LOK Worker] Bold error:",u),i.push({operation:"Bold",success:!1,error:String(u)});}console.log("[LOK Worker] Testing Italic formatting...");try{c.postUnoCommand(o,".uno:GoRight"),c.postUnoCommand(o,".uno:WordRightSel");let u=c.getTextSelection(o,"text/plain;charset=utf-8");console.log(`[LOK Worker] Selected for italic: "${u}"`),c.postUnoCommand(o,".uno:Italic"),console.log("[LOK Worker] Sent Italic");let g=c.getCommandValues(o,".uno:Italic");console.log(`[LOK Worker] Italic state: ${g}`),i.push({operation:"Italic",success:!0,result:{selectedText:u,italicState:g}});}catch(u){console.error("[LOK Worker] Italic error:",u),i.push({operation:"Italic",success:!1,error:String(u)});}console.log("[LOK Worker] Testing getCharacterFormatting via STATE_CHANGED callbacks...");try{let u=c.getCallbackEventCount();console.log(`[LOK Worker] Existing events in queue: ${u}`);let g=c.pollStateChanges();console.log(`[LOK Worker] Existing STATE_CHANGED events: ${g.size}`);for(let[C,T]of g.entries())console.log(`[LOK Worker] ${C} = ${T}`);c.clearCallbackQueue(),c.postUnoCommand(o,".uno:GoToStartOfDoc"),c.flushCallbacks(o),c.postUnoCommand(o,".uno:WordRightSel"),c.flushCallbacks(o);let f=c.getCallbackEventCount(),P=c.hasCallbackEvents();console.log(`[LOK Worker] Event count after WordRightSel: ${f}, hasEvents: ${P}`);let p=c.pollStateChanges();console.log(`[LOK Worker] State changes after selection: ${p.size}`);for(let[C,T]of p.entries())console.log(`[LOK Worker] ${C} = ${T}`);for(let[C,T]of g.entries())p.has(C)||p.set(C,T);let O={};for(let[C,T]of p.entries())O[C]=T;console.log(`[LOK Worker] Received ${p.size} state changes:`);for(let[C,T]of p.entries())console.log(` ${C} = ${T}`);let _=p.get(".uno:Bold")??null,k=p.get(".uno:Italic")??null,N=p.get(".uno:Underline")??null,M=p.get(".uno:CharFontName")??null,b=p.get(".uno:FontHeight")??null,B=p.get(".uno:Color")??p.get(".uno:CharColor")??null;console.log("[LOK Worker] Character formatting from STATE_CHANGED:"),console.log(` Bold: ${_}`),console.log(` Italic: ${k}`),console.log(` Underline: ${N}`),console.log(` FontName: ${M}`),console.log(` FontSize: ${b}`),console.log(` Color: ${B}`),i.push({operation:"getCharacterFormatting",success:!0,result:{stateChangeCount:p.size,note:p.size===0?"Callback queue empty - C++ shims may need to be added to WASM build":void 0,bold:_,italic:k,underline:N,fontName:M,fontSize:b,color:B,allStates:O}});}catch(u){console.error("[LOK Worker] getCharacterFormatting error:",u),i.push({operation:"getCharacterFormatting",success:!1,error:String(u)});}console.log("[LOK Worker] Testing setTextSelection...");try{c.resetSelection(o),c.setTextSelection(o,0,500,500),c.setTextSelection(o,1,3e3,500);let u=c.getTextSelection(o,"text/plain;charset=utf-8");console.log(`[LOK Worker] Coordinate-selected text: "${u}"`),i.push({operation:"setTextSelection",success:!0,result:{selectedText:u}});}catch(u){console.error("[LOK Worker] setTextSelection error:",u),i.push({operation:"setTextSelection",success:!1,error:String(u)});}console.log("[LOK Worker] Testing document save...");try{let u=t||"docx",f={docx:"docx",doc:"doc",odt:"odt",xlsx:"xlsx",xls:"xls",ods:"ods",pptx:"pptx",ppt:"ppt",odp:"odp"}[u]||u;c.documentSaveAs(o,n,f,"");let P=E.FS.readFile(n);i.push({operation:"documentSave",success:P.length>0,result:{savedBytes:P.length,originalBytes:e.length}});}catch(u){console.error("[LOK Worker] Save error:",u),i.push({operation:"documentSave",success:!1,error:String(u)});}let m=`${i.filter(u=>u.success).length}/${i.length} operations succeeded`;console.log(`[LOK Worker] Test results summary: ${m}`),y({type:"testLokOperations",id:l.id,testLokOperationsResult:{operations:i,summary:m}});}catch(a){console.error("[LOK Worker] Error in handleTestLokOperations:",a),y({type:"error",id:l.id,error:a instanceof Error?a.message:String(a)});}finally{if(o!==0&&c){try{c.unregisterCallback(o);}catch{}if(s>=0)try{c.destroyView(o,s);}catch{}try{c.documentDestroy(o);}catch{}}if(E){try{E.FS.unlink(r);}catch{}try{E.FS.unlink(n);}catch{}}}}async function Me(l){if(!w||!E||!c){y({type:"error",id:l.id,error:"Worker not initialized"});return}let e=l.inputData,t=l.inputExt||"docx";if(!e||e.length===0){y({type:"error",id:l.id,error:"No input data provided"});return}try{let r=`session_${++be}_${Date.now()}`,n=`/tmp/edit_${r}.${t}`;E.FS.writeFile(n,e);let o=c.documentLoad(n);if(o===0){let h=c.getError();E.FS.unlink(n),y({type:"error",id:l.id,error:`Failed to load document: ${String(h)}`});return}c.documentInitializeForRendering(o);let s=c.createView(o);c.setView(o,s),c.registerCallback(o),c.postUnoCommand(o,".uno:Edit");let i=se(c,o),a=i.getDocumentType(),d=c.documentGetParts(o);W.set(r,{sessionId:r,docPtr:o,filePath:n,editor:i,documentType:a}),console.log(`[LOK Worker] Opened document session: ${r}, type: ${a}, pages: ${d}`),y({type:"editorSession",id:l.id,editorSession:{sessionId:r,documentType:a,pageCount:d}});}catch(r){console.error("[LOK Worker] Error in handleOpenDocument:",r),y({type:"error",id:l.id,error:r instanceof Error?r.message:String(r)});}}async function Be(l){let{sessionId:e,editorMethod:t,editorArgs:r}=l;if(!e||!t){y({type:"error",id:l.id,error:"Missing sessionId or editorMethod"});return}let n=W.get(e);if(!n){y({type:"error",id:l.id,error:`Session not found: ${e}`});return}try{let{editor:o}=n,s=r||[],i=o[t];if(typeof i!="function"){y({type:"error",id:l.id,error:`Unknown editor method: ${t}`});return}let a=i.apply(o,s),d=a.data;a.data instanceof Map&&(d=Object.fromEntries(a.data)),y({type:"editorOperationResult",id:l.id,editorOperationResult:{success:a.success,verified:a.verified,data:d,error:a.error,suggestion:a.suggestion}});}catch(o){console.error(`[LOK Worker] Error in handleEditorOperation (${t}):`,o),y({type:"error",id:l.id,error:o instanceof Error?o.message:String(o)});}}async function Ve(l){let{sessionId:e}=l;if(!e){y({type:"error",id:l.id,error:"Missing sessionId"});return}let t=W.get(e);if(!t){y({type:"error",id:l.id,error:`Session not found: ${e}`});return}try{let{docPtr:r,filePath:n}=t,o;if(E)try{let s=n.split(".").pop()||"docx";c?.documentSaveAs(r,n,s,""),o=E.FS.readFile(n);}catch(s){console.warn("[LOK Worker] Could not save document:",s);}if(c&&r!==0){try{c.unregisterCallback(r);}catch{}try{c.documentDestroy(r);}catch{}}if(E)try{E.FS.unlink(n);}catch{}W.delete(e),console.log(`[LOK Worker] Closed document session: ${e}`),y({type:"documentClosed",id:l.id,data:o});}catch(r){console.error("[LOK Worker] Error in handleCloseDocument:",r),y({type:"error",id:l.id,error:r instanceof Error?r.message:String(r)});}}function ze(l){console.log("handleDestroy");for(let[,e]of W)try{if(c&&e.docPtr!==0){try{c.unregisterCallback(e.docPtr);}catch{}try{c.documentDestroy(e.docPtr);}catch{}}if(E)try{E.FS.unlink(e.filePath);}catch{}}catch{}if(W.clear(),A(),D){try{D.destroy();}catch{}D=null,c=null;}else if(c){try{c.destroy();}catch{}c=null;}if(E&&E.PThread?.terminateAllThreads)try{E.PThread.terminateAllThreads();}catch{}E=null,w=false,y({type:"ready",id:l.id}),setTimeout(()=>self.close(),100);}self.onmessage=async l=>{let e=l.data;switch(e.type){case "init":await Te(e);break;case "convert":await Re(e);break;case "getPageCount":await Ae(e);break;case "renderPreviews":await Ie(e);break;case "renderSinglePage":await xe(e);break;case "renderPageViaConvert":await Fe(e);break;case "renderPageFullQuality":await De(e);break;case "getDocumentInfo":await We(e);break;case "getLokInfo":await Ne(e);break;case "editText":await Ue(e);break;case "renderPageRectangles":await Ke(e);break;case "testLokOperations":await $e(e);break;case "openDocument":await Me(e);break;case "editorOperation":await Be(e);break;case "closeDocument":await Ve(e);break;case "destroy":ze(e);break}};self.postMessage({type:"loaded"}); +})();//# sourceMappingURL=browser.worker.global.js.map +//# sourceMappingURL=browser.worker.global.js.map \ No newline at end of file diff --git a/public/libreoffice-wasm/soffice.data.gz b/public/libreoffice-wasm/soffice.data.gz new file mode 100644 index 0000000..96bd8bc Binary files /dev/null and b/public/libreoffice-wasm/soffice.data.gz differ diff --git a/public/libreoffice-wasm/soffice.js b/public/libreoffice-wasm/soffice.js new file mode 100644 index 0000000..eaf38d4 --- /dev/null +++ b/public/libreoffice-wasm/soffice.js @@ -0,0 +1,2 @@ +if(typeof global!=="undefined"){var Module=global.Module=global.Module||{}} +function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPU8}function GROWABLE_HEAP_I16(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAP16}function GROWABLE_HEAP_U16(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPU16}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPU32}function GROWABLE_HEAP_F32(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPF32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPF64}var Module=typeof Module!="undefined"?Module:{};var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof WorkerGlobalScope!="undefined";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string"&&process.type!="renderer";var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var ENVIRONMENT_IS_PTHREAD=ENVIRONMENT_IS_WORKER&&self.name?.startsWith("em-pthread");if(ENVIRONMENT_IS_NODE){var worker_threads=require("worker_threads");global.Worker=worker_threads.Worker;ENVIRONMENT_IS_WORKER=!worker_threads.isMainThread;ENVIRONMENT_IS_PTHREAD=ENVIRONMENT_IS_WORKER&&worker_threads["workerData"]=="em-pthread"}if(!("preRun"in Module))Module["preRun"]=[];Module.preRun.push(function(){ENV.SAL_LOG="+WARN"});var Module=typeof Module!="undefined"?Module:{};Module["expectedDataFileDownloads"]??=0;Module["expectedDataFileDownloads"]++;(()=>{var isPthread=typeof ENVIRONMENT_IS_PTHREAD!="undefined"&&ENVIRONMENT_IS_PTHREAD;var isWasmWorker=typeof ENVIRONMENT_IS_WASM_WORKER!="undefined"&&ENVIRONMENT_IS_WASM_WORKER;if(isPthread||isWasmWorker)return;var isNode=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";function loadPackage(metadata){var PACKAGE_PATH="";if(typeof window==="object"){PACKAGE_PATH=window["encodeURIComponent"](window.location.pathname.substring(0,window.location.pathname.lastIndexOf("/"))+"/")}else if(typeof process==="undefined"&&typeof location!=="undefined"){PACKAGE_PATH=encodeURIComponent(location.pathname.substring(0,location.pathname.lastIndexOf("/"))+"/")}var PACKAGE_NAME="soffice.data";var REMOTE_PACKAGE_BASE="soffice.data";var REMOTE_PACKAGE_NAME=Module["locateFile"]?Module["locateFile"](REMOTE_PACKAGE_BASE,""):REMOTE_PACKAGE_BASE;var REMOTE_PACKAGE_SIZE=metadata["remote_package_size"];function fetchRemotePackage(packageName,packageSize,callback,errback){if(isNode){require("fs").readFile(packageName,(err,contents)=>{if(err){errback(err)}else{callback(contents.buffer)}});return}Module["dataFileDownloads"]??={};fetch(packageName).catch(cause=>Promise.reject(new Error(`Network Error: ${packageName}`,{cause}))).then(response=>{if(!response.ok){return Promise.reject(new Error(`${response.status}: ${response.url}`))}if(!response.body&&response.arrayBuffer){return response.arrayBuffer().then(callback)}const reader=response.body.getReader();const iterate=()=>reader.read().then(handleChunk).catch(cause=>Promise.reject(new Error(`Unexpected error while handling : ${response.url} ${cause}`,{cause})));const chunks=[];const headers=response.headers;const total=Number(headers.get("Content-Length")??packageSize);let loaded=0;const handleChunk=({done,value})=>{if(!done){chunks.push(value);loaded+=value.length;Module["dataFileDownloads"][packageName]={loaded,total};let totalLoaded=0;let totalSize=0;for(const download of Object.values(Module["dataFileDownloads"])){totalLoaded+=download.loaded;totalSize+=download.total}Module["setStatus"]?.(`Downloading data... (${totalLoaded}/${totalSize})`);return iterate()}else{const packageData=new Uint8Array(chunks.map(c=>c.length).reduce((a,b)=>a+b,0));let offset=0;for(const chunk of chunks){packageData.set(chunk,offset);offset+=chunk.length}callback(packageData.buffer)}};Module["setStatus"]?.("Downloading data...");return iterate()})}function handleError(error){console.error("package error:",error)}var fetchedCallback=null;var fetched=Module["getPreloadedPackage"]?Module["getPreloadedPackage"](REMOTE_PACKAGE_NAME,REMOTE_PACKAGE_SIZE):null;if(!fetched)fetchRemotePackage(REMOTE_PACKAGE_NAME,REMOTE_PACKAGE_SIZE,data=>{if(fetchedCallback){fetchedCallback(data);fetchedCallback=null}else{fetched=data}},handleError);function runWithFS(Module){function assert(check,msg){if(!check)throw msg+(new Error).stack}Module["FS_createPath"]("/","android",true,true);Module["FS_createPath"]("/android","default-document",true,true);Module["FS_createPath"]("/","instdir",true,true);Module["FS_createPath"]("/instdir","presets",true,true);Module["FS_createPath"]("/instdir/presets","autotext",true,true);Module["FS_createPath"]("/instdir/presets","basic",true,true);Module["FS_createPath"]("/instdir/presets/basic","Standard",true,true);Module["FS_createPath"]("/instdir/presets","config",true,true);Module["FS_createPath"]("/instdir/presets","gallery",true,true);Module["FS_createPath"]("/instdir","program",true,true);Module["FS_createPath"]("/instdir/program","resource",true,true);Module["FS_createPath"]("/instdir/program/resource","common",true,true);Module["FS_createPath"]("/instdir/program/resource/common","fonts",true,true);Module["FS_createPath"]("/instdir/program","services",true,true);Module["FS_createPath"]("/instdir/program","shell",true,true);Module["FS_createPath"]("/instdir/program","types",true,true);Module["FS_createPath"]("/instdir","share",true,true);Module["FS_createPath"]("/instdir/share","config",true,true);Module["FS_createPath"]("/instdir/share/config","soffice.cfg",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","cui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/cui","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","desktop",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/desktop","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","editeng",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/editeng","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","filter",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/filter","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","formula",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/formula","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","fps",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/fps","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","modules",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules","StartModule",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/StartModule","menubar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules","scalc",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/scalc","menubar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/scalc","popupmenu",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/scalc","statusbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/scalc","toolbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/scalc","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules","schart",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/schart","menubar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/schart","popupmenu",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/schart","statusbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/schart","toolbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/schart","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules","sdraw",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sdraw","menubar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sdraw","popupmenu",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sdraw","statusbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sdraw","toolbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sdraw","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules","sglobal",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sglobal","menubar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sglobal","popupmenu",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sglobal","statusbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sglobal","toolbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules","simpress",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/simpress","menubar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/simpress","popupmenu",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/simpress","statusbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/simpress","toolbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/simpress","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules","smath",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/smath","menubar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/smath","popupmenu",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/smath","statusbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/smath","toolbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/smath","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules","sweb",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sweb","menubar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sweb","popupmenu",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sweb","statusbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/sweb","toolbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules","swform",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swform","menubar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swform","popupmenu",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swform","statusbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swform","toolbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules","swreport",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swreport","menubar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swreport","popupmenu",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swreport","statusbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swreport","toolbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules","swriter",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swriter","menubar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swriter","popupmenu",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swriter","statusbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swriter","toolbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swriter","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules","swxform",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swxform","menubar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swxform","popupmenu",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swxform","statusbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/modules/swxform","toolbar",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","sfx",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/sfx","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","simpress",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","svt",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/svt","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","svx",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/svx","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","uui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/uui","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","vcl",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/vcl","ui",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg","writerperfect",true,true);Module["FS_createPath"]("/instdir/share/config/soffice.cfg/writerperfect","ui",true,true);Module["FS_createPath"]("/instdir/share/config","wizard",true,true);Module["FS_createPath"]("/instdir/share/config/wizard","form",true,true);Module["FS_createPath"]("/instdir/share/config/wizard/form","styles",true,true);Module["FS_createPath"]("/instdir/share","filter",true,true);Module["FS_createPath"]("/instdir/share","fontconfig",true,true);Module["FS_createPath"]("/instdir/share/fontconfig","conf.d",true,true);Module["FS_createPath"]("/instdir/share","fonts",true,true);Module["FS_createPath"]("/instdir/share/fonts","truetype",true,true);Module["FS_createPath"]("/instdir/share","gallery",true,true);Module["FS_createPath"]("/instdir/share","liblangtag",true,true);Module["FS_createPath"]("/instdir/share/liblangtag","common",true,true);Module["FS_createPath"]("/instdir/share/liblangtag/common","bcp47",true,true);Module["FS_createPath"]("/instdir/share/liblangtag/common","supplemental",true,true);Module["FS_createPath"]("/instdir/share","registry",true,true);Module["FS_createPath"]("/instdir/share/registry","res",true,true);function DataRequest(start,end,audio){this.start=start;this.end=end;this.audio=audio}DataRequest.prototype={requests:{},open:function(mode,name){this.name=name;this.requests[name]=this;Module["addRunDependency"](`fp ${this.name}`)},send:function(){},onload:function(){var byteArray=this.byteArray.subarray(this.start,this.end);this.finish(byteArray)},finish:function(byteArray){var that=this;Module["FS_createDataFile"](this.name,null,byteArray,true,true,true);Module["removeRunDependency"](`fp ${that.name}`);this.requests[this.name]=null}};var files=metadata["files"];for(var i=0;i{throw toThrow};var _scriptName=typeof document!="undefined"?document.currentScript?.src:undefined;if(ENVIRONMENT_IS_NODE){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){if(typeof process=="undefined"||!process.release||process.release.name!=="node")throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");var nodeVersion=process.versions.node;var numericVersion=nodeVersion.split(".").slice(0,3);numericVersion=numericVersion[0]*1e4+numericVersion[1]*100+numericVersion[2].split("-")[0]*1;if(numericVersion<16e4){throw new Error("This emscripten-generated code requires node v16.0.0 (detected v"+nodeVersion+")")}var fs=require("fs");var nodePath=require("path");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);assert(Buffer.isBuffer(ret));return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");assert(binary?Buffer.isBuffer(ret):typeof ret=="string");return ret};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);if(typeof module!="undefined"){module["exports"]=Module}quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_SHELL){if(typeof process=="object"&&typeof require==="function"||typeof window=="object"||typeof WorkerGlobalScope!="undefined")throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)")}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}if(!(typeof window=="object"||typeof WorkerGlobalScope!="undefined"))throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");if(!ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{throw new Error("environment detection error")}var defaultPrint=console.log.bind(console);var defaultPrintErr=console.error.bind(console);if(ENVIRONMENT_IS_NODE){defaultPrint=(...args)=>fs.writeSync(1,args.join(" ")+"\n");defaultPrintErr=(...args)=>fs.writeSync(2,args.join(" ")+"\n")}var out=Module["print"]||defaultPrint;var err=Module["printErr"]||defaultPrintErr;Object.assign(Module,moduleOverrides);moduleOverrides=null;checkIncomingModuleAPI();if(Module["arguments"])arguments_=Module["arguments"];legacyModuleProp("arguments","arguments_");if(Module["thisProgram"])thisProgram=Module["thisProgram"];legacyModuleProp("thisProgram","thisProgram");assert(typeof Module["memoryInitializerPrefixURL"]=="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]=="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]=="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]=="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]=="undefined","Module.read option was removed");assert(typeof Module["readAsync"]=="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]=="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]=="undefined","Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)");assert(typeof Module["TOTAL_MEMORY"]=="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");legacyModuleProp("asm","wasmExports");legacyModuleProp("readAsync","readAsync");legacyModuleProp("readBinary","readBinary");legacyModuleProp("setWindowTitle","setWindowTitle");assert(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER||ENVIRONMENT_IS_NODE,"Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)");assert(!ENVIRONMENT_IS_SHELL,"shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.");var wasmBinary=Module["wasmBinary"];legacyModuleProp("wasmBinary","wasmBinary");if(typeof WebAssembly!="object"){err("no native wasm support detected")}function intArrayFromBase64(s){if(typeof ENVIRONMENT_IS_NODE!="undefined"&&ENVIRONMENT_IS_NODE){var buf=Buffer.from(s,"base64");return new Uint8Array(buf.buffer,buf.byteOffset,buf.length)}var decoded=atob(s);var bytes=new Uint8Array(decoded.length);for(var i=0;ionmessage({data:msg}));Object.assign(globalThis,{self:global,postMessage:msg=>parentPort.postMessage(msg)})}var initializedJS=false;function threadPrintErr(...args){var text=args.join(" ");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+"\n");return}console.error(text)}if(!Module["printErr"])err=threadPrintErr;dbg=threadPrintErr;function threadAlert(...args){var text=args.join(" ");postMessage({cmd:"alert",text,threadId:_pthread_self()})}self.alert=threadAlert;self.onunhandledrejection=e=>{throw e.reason||e};function handleMessage(e){try{var msgData=e["data"];var cmd=msgData.cmd;if(cmd==="load"){workerID=msgData.workerID;let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{postMessage({cmd:"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};for(const handler of msgData.handlers){if(!Module[handler]||Module[handler].proxy){Module[handler]=(...args)=>{postMessage({cmd:"callHandler",handler,args})};if(handler=="print")out=Module[handler];if(handler=="printErr")err=Module[handler]}}wasmMemory=msgData.wasmMemory;updateMemoryViews();wasmModuleReceived(msgData.wasmModule)}else if(cmd==="run"){assert(msgData.pthread_ptr);establishStackSpace(msgData.pthread_ptr);__emscripten_thread_init(msgData.pthread_ptr,0,0,1,0,0);PThread.receiveObjectTransfer(msgData);PThread.threadInitTLS();__emscripten_thread_mailbox_await(msgData.pthread_ptr);if(!initializedJS){__embind_initialize_bindings();initializedJS=true}try{invokeEntryPoint(msgData.start_routine,msgData.arg)}catch(ex){if(ex!="unwind"){throw ex}}}else if(msgData.target==="setimmediate"){}else if(cmd==="checkMailbox"){if(initializedJS){checkMailbox()}}else if(cmd){err(`worker: received unknown command ${cmd}`);err(msgData)}}catch(ex){err(`worker: onmessage() captured an uncaught exception: ${ex}`);if(ex?.stack)err(ex.stack);__emscripten_thread_crashed();throw ex}}self.onmessage=handleMessage}assert(!Module["STACK_SIZE"],"STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time");assert(typeof Int32Array!="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!=undefined&&Int32Array.prototype.set!=undefined,"JS engine does not provide full typed array support");if(!ENVIRONMENT_IS_PTHREAD){if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||1073741824;legacyModuleProp("INITIAL_MEMORY","INITIAL_MEMORY");assert(INITIAL_MEMORY>=5242880,"INITIAL_MEMORY should be larger than STACK_SIZE, was "+INITIAL_MEMORY+"! (STACK_SIZE="+5242880+")");wasmMemory=new WebAssembly.Memory({initial:INITIAL_MEMORY/65536,maximum:65536,shared:true})}updateMemoryViews()}function writeStackCookie(){var max=_emscripten_stack_get_end();assert((max&3)==0);if(max==0){max+=4}GROWABLE_HEAP_U32()[max>>>2>>>0]=34821223;GROWABLE_HEAP_U32()[max+4>>>2>>>0]=2310721022;GROWABLE_HEAP_U32()[0>>>2>>>0]=1668509029}function checkStackCookie(){if(ABORT)return;var max=_emscripten_stack_get_end();if(max==0){max+=4}var cookie1=GROWABLE_HEAP_U32()[max>>>2>>>0];var cookie2=GROWABLE_HEAP_U32()[max+4>>>2>>>0];if(cookie1!=34821223||cookie2!=2310721022){abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`)}if(GROWABLE_HEAP_U32()[0>>>2>>>0]!=1668509029){abort("Runtime error: The application has corrupted its heap memory area (address zero)!")}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){assert(!ENVIRONMENT_IS_PTHREAD);if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){assert(!runtimeInitialized);runtimeInitialized=true;if(ENVIRONMENT_IS_PTHREAD)return startWorker(Module);checkStackCookie();SOCKFS.root=FS.mount(SOCKFS,{},null);if(!Module["noFSInit"]&&!FS.initialized)FS.init();FS.ignorePermissions=false;TTY.init();PIPEFS.root=FS.mount(PIPEFS,{},null);callRuntimeCallbacks(__ATINIT__)}function preMain(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__)}function postRun(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPreMain(cb){__ATMAIN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var runDependencies=0;var dependenciesFulfilled=null;var runDependencyTracking={};var runDependencyWatcher=null;function getUniqueRunDependency(id){var orig=id;while(1){if(!runDependencyTracking[id])return id;id=orig+Math.random()}}function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies);if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!="undefined"){runDependencyWatcher=setInterval(()=>{if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:")}err(`dependency: ${dep}`)}if(shown){err("(end of list)")}},1e4)}}else{err("warning: run dependency added without ID")}}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id]}else{err("warning: run dependency removed without ID")}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;if(runtimeInitialized){___trap()}var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function createExportWrapper(name,nargs){return(...args)=>{assert(runtimeInitialized,`native function \`${name}\` called before runtime initialization`);var f=wasmExports[name];assert(f,`exported native function \`${name}\` not found`);assert(args.length<=nargs,`native function \`${name}\` called with ${args.length} args but expects ${nargs}`);return f(...args)}}function findWasmBinary(){var f="soffice.wasm";if(!isDataURI(f)){return locateFile(f)}return f}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);if(isFileURI(wasmBinaryFile)){err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`)}abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){assignWasmImports();return{env:wasmImports,wasi_snapshot_preview1:wasmImports}}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;wasmExports=applySignatureConversions(wasmExports);registerTLSInit(wasmExports["_emscripten_tls_init"]);wasmTable=wasmExports["__indirect_function_table"];Module["wasmTable"]=wasmTable;assert(wasmTable,"table not found in wasm exports");addOnInit(wasmExports["__wasm_call_ctors"]);wasmModule=module;removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");var trueModule=Module;function receiveInstantiationResult(result){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(result["instance"],result["module"])}var info=getWasmImports();if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);return false}}if(ENVIRONMENT_IS_PTHREAD){return new Promise(resolve=>{wasmModuleReceived=module=>{var instance=new WebAssembly.Instance(module,getWasmImports());receiveInstance(instance,module);resolve()}})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);receiveInstantiationResult(result);return result}(()=>{var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw"Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)"})();if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)")}function legacyModuleProp(prop,newName,incoming=true){if(!Object.getOwnPropertyDescriptor(Module,prop)){Object.defineProperty(Module,prop,{configurable:true,get(){let extra=incoming?" (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)":"";abort(`\`Module.${prop}\` has been replaced by \`${newName}\``+extra)}})}}function ignoredModuleProp(prop){if(Object.getOwnPropertyDescriptor(Module,prop)){abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`)}}function isExportedByForceFilesystem(name){return name==="FS_createPath"||name==="FS_createDataFile"||name==="FS_createPreloadedFile"||name==="FS_unlink"||name==="addRunDependency"||name==="FS_createLazyFile"||name==="FS_createDevice"||name==="removeRunDependency"}function hookGlobalSymbolAccess(sym,func){if(typeof globalThis!="undefined"&&!Object.getOwnPropertyDescriptor(globalThis,sym)){Object.defineProperty(globalThis,sym,{configurable:true,get(){func();return undefined}})}}function missingGlobal(sym,msg){hookGlobalSymbolAccess(sym,()=>{warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`)})}missingGlobal("buffer","Please use HEAP8.buffer or wasmMemory.buffer");missingGlobal("asm","Please use wasmExports instead");function missingLibrarySymbol(sym){hookGlobalSymbolAccess(sym,()=>{var msg=`\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`;var librarySymbol=sym;if(!librarySymbol.startsWith("_")){librarySymbol="$"+sym}msg+=` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`;if(isExportedByForceFilesystem(sym)){msg+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"}warnOnce(msg)});unexportedRuntimeSymbol(sym)}function unexportedRuntimeSymbol(sym){if(ENVIRONMENT_IS_PTHREAD){return}if(!Object.getOwnPropertyDescriptor(Module,sym)){Object.defineProperty(Module,sym,{configurable:true,get(){var msg=`'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`;if(isExportedByForceFilesystem(sym)){msg+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"}abort(msg)}})}}function dbg(...args){if(ENVIRONMENT_IS_NODE&&fs){fs.writeSync(2,args.join(" ")+"\n")}else console.warn(...args)}var ASM_CONSTS={52007737:$0=>{window.open(UTF8ToString($0))}};function jsRegisterChar(raw){Module.registerType(raw,{name:"sal_Unicode",fromWireType(ptr){let str=String.fromCharCode(Module.HEAPU16[ptr>>1]);return str},toWireType(destructors,value){if(typeof value!="string"||value.length!==1){Module.throwBindingError("Cannot pass anything but 1-element string to C++ char16_t")}let data=Module._malloc(2);Module.HEAPU16[data>>1]=value.charCodeAt(0);if(destructors!==null){destructors.push(Module._free,data)}return data},argPackAdvance:8,readValueFromPointer(pointer){return this.fromWireType(Module.HEAPU32[pointer>>2])},destructorFunction(ptr){Module._free(ptr)}})}function jsRegisterString(raw){Module.registerType(raw,{name:"rtl::OUString",fromWireType(ptr){let data=Module.HEAPU32[ptr>>2];let length=Module.HEAPU32[(data>>2)+1];let buffer=data+8;let str="";for(let i=0;i>1)+i];str+=String.fromCharCode(c)}Module.rtl_uString_release(data);Module._free(ptr);return str},toWireType(destructors,value){if(typeof value!="string"){Module.throwBindingError("Cannot pass non-string to C++ OUString")}let data=Module._malloc(8+(value.length+1)*2);Module.HEAPU32[data>>2]=1;Module.HEAPU32[(data>>2)+1]=value.length;let buffer=data+8;for(let i=0;i>1)+i]=value.charCodeAt(i)}Module.HEAPU16[(buffer>>1)+value.length]=0;let ptr=Module._malloc(4);Module.HEAPU32[ptr>>2]=data;if(destructors!==null){destructors.push(Module._free,ptr)}return ptr},argPackAdvance:8,readValueFromPointer(pointer){return this.fromWireType(Module.HEAPU32[pointer>>2])},destructorFunction(ptr){Module._free(ptr)}})}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var terminateWorker=worker=>{worker.terminate();worker.onmessage=e=>{var cmd=e["data"].cmd;err(`received "${cmd}" command from terminated worker: ${worker.workerID}`)}};var cleanupThread=pthread_ptr=>{assert(!ENVIRONMENT_IS_PTHREAD,"Internal Error! cleanupThread() can only ever be called from main application thread!");assert(pthread_ptr,"Internal Error! Null pthread_ptr in cleanupThread!");var worker=PThread.pthreads[pthread_ptr];assert(worker);PThread.returnWorkerToPool(worker)};var spawnThread=threadParams=>{assert(!ENVIRONMENT_IS_PTHREAD,"Internal Error! spawnThread() can only ever be called from main application thread!");assert(threadParams.pthread_ptr,"Internal error, no pthread ptr!");var worker=PThread.getNewWorker();if(!worker){return 6}assert(!worker.pthread_ptr,"Internal error!");PThread.runningWorkers.push(worker);PThread.pthreads[threadParams.pthread_ptr]=worker;worker.pthread_ptr=threadParams.pthread_ptr;var msg={cmd:"run",start_routine:threadParams.startRoutine,arg:threadParams.arg,pthread_ptr:threadParams.pthread_ptr};if(ENVIRONMENT_IS_NODE){worker.unref()}worker.postMessage(msg,threadParams.transferList);return 0};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var stackSave=()=>_emscripten_stack_get_current();var stackRestore=val=>__emscripten_stack_restore(val);var stackAlloc=sz=>__emscripten_stack_alloc(sz);var INT53_MAX=9007199254740992;var INT53_MIN=-9007199254740992;var bigintToI53Checked=num=>numINT53_MAX?NaN:Number(num);var proxyToMainThread=(funcIndex,emAsmAddr,sync,...callArgs)=>{var serializedNumCallArgs=callArgs.length*2;var sp=stackSave();var args=stackAlloc(serializedNumCallArgs*8);var b=args>>>3;for(var i=0;i>>0]=arg}}var rtn=__emscripten_run_on_main_thread_js(funcIndex,emAsmAddr,serializedNumCallArgs,args,sync);stackRestore(sp);return rtn};function _proc_exit(code){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(0,0,1,code);EXITSTATUS=code;if(!keepRuntimeAlive()){PThread.terminateAllThreads();Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))}var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}checkStackCookie();if(e instanceof WebAssembly.RuntimeError){if(_emscripten_stack_get_current()<=0){err("Stack overflow detected. You can try increasing -sSTACK_SIZE (currently set to 5242880)")}}quit_(1,e)};var runtimeKeepalivePop=()=>{assert(runtimeKeepaliveCounter>0);runtimeKeepaliveCounter-=1};function exitOnMainThread(returnCode){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(1,0,0,returnCode);runtimeKeepalivePop();_exit(returnCode)}var exitJS=(status,implicit)=>{EXITSTATUS=status;checkUnflushedContent();if(ENVIRONMENT_IS_PTHREAD){assert(!implicit);exitOnMainThread(status);throw"unwind"}if(keepRuntimeAlive()&&!implicit){var msg=`program exited (with status: ${status}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`;err(msg)}_proc_exit(status)};var _exit=exitJS;var ptrToString=ptr=>{assert(typeof ptr==="number");return"0x"+ptr.toString(16).padStart(8,"0")};var PThread={unusedWorkers:[],runningWorkers:[],tlsInitFunctions:[],pthreads:{},nextWorkerID:1,debugInit(){function pthreadLogPrefix(){var t=0;if(runtimeInitialized&&typeof _pthread_self!="undefined"){t=_pthread_self()}return`w:${workerID},t:${ptrToString(t)}: `}var origDbg=dbg;dbg=(...args)=>origDbg(pthreadLogPrefix()+args.join(" "))},init(){PThread.debugInit();if(!ENVIRONMENT_IS_PTHREAD){PThread.initMainThread()}},initMainThread(){var pthreadPoolSize=4;while(pthreadPoolSize--){PThread.allocateUnusedWorker()}addOnPreRun(()=>{addRunDependency("loading-workers");PThread.loadWasmModuleToAllWorkers(()=>removeRunDependency("loading-workers"))})},terminateAllThreads:()=>{assert(!ENVIRONMENT_IS_PTHREAD,"Internal Error! terminateAllThreads() can only ever be called from main application thread!");for(var worker of PThread.runningWorkers){terminateWorker(worker)}for(var worker of PThread.unusedWorkers){terminateWorker(worker)}PThread.unusedWorkers=[];PThread.runningWorkers=[];PThread.pthreads={}},returnWorkerToPool:worker=>{var pthread_ptr=worker.pthread_ptr;delete PThread.pthreads[pthread_ptr];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);worker.pthread_ptr=0;if(ENVIRONMENT_IS_NODE){worker.unref()}__emscripten_thread_free_data(pthread_ptr)},receiveObjectTransfer(data){},threadInitTLS(){PThread.tlsInitFunctions.forEach(f=>f())},loadWasmModuleToWorker:worker=>new Promise(onFinishedLoading=>{worker.onmessage=e=>{var d=e["data"];var cmd=d.cmd;if(d.targetThread&&d.targetThread!=_pthread_self()){var targetWorker=PThread.pthreads[d.targetThread];if(targetWorker){targetWorker.postMessage(d,d.transferList)}else{err(`Internal error! Worker sent a message "${cmd}" to target pthread ${d.targetThread}, but that thread no longer exists!`)}return}if(cmd==="checkMailbox"){checkMailbox()}else if(cmd==="spawnThread"){spawnThread(d)}else if(cmd==="cleanupThread"){cleanupThread(d.thread)}else if(cmd==="loaded"){worker.loaded=true;if(ENVIRONMENT_IS_NODE&&!worker.pthread_ptr){worker.unref()}onFinishedLoading(worker)}else if(cmd==="alert"){alert(`Thread ${d.threadId}: ${d.text}`)}else if(d.target==="setimmediate"){worker.postMessage(d)}else if(cmd==="callHandler"){Module[d.handler](...d.args)}else if(cmd){err(`worker sent an unknown command ${cmd}`)}};worker.onerror=e=>{var message="worker sent an error!";if(worker.pthread_ptr){message=`Pthread ${ptrToString(worker.pthread_ptr)} sent an error!`}err(`${message} ${e.filename}:${e.lineno}: ${e.message}`);throw e};if(ENVIRONMENT_IS_NODE){worker.on("message",data=>worker.onmessage({data}));worker.on("error",e=>worker.onerror(e))}assert(wasmMemory instanceof WebAssembly.Memory,"WebAssembly memory should have been loaded by now!");assert(wasmModule instanceof WebAssembly.Module,"WebAssembly Module should have been loaded by now!");var handlers=[];var knownHandlers=["onExit","onAbort","print","printErr"];for(var handler of knownHandlers){if(Module.propertyIsEnumerable(handler)){handlers.push(handler)}}worker.workerID=PThread.nextWorkerID++;worker.postMessage({cmd:"load",handlers,wasmMemory,wasmModule,workerID:worker.workerID})}),loadWasmModuleToAllWorkers(onMaybeReady){if(ENVIRONMENT_IS_PTHREAD){return onMaybeReady()}let pthreadPoolReady=Promise.all(PThread.unusedWorkers.map(PThread.loadWasmModuleToWorker));pthreadPoolReady.then(onMaybeReady)},allocateUnusedWorker(){var worker;var workerOptions={workerData:"em-pthread",name:"em-pthread-"+PThread.nextWorkerID};var pthreadMainJs=_scriptName;if(Module["mainScriptUrlOrBlob"]){pthreadMainJs=Module["mainScriptUrlOrBlob"];if(typeof pthreadMainJs!="string"){pthreadMainJs=URL.createObjectURL(pthreadMainJs)}}worker=new Worker(pthreadMainJs,workerOptions);PThread.unusedWorkers.push(worker)},getNewWorker(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0])}return PThread.unusedWorkers.pop()}};var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var establishStackSpace=pthread_ptr=>{updateMemoryViews();var stackHigh=GROWABLE_HEAP_U32()[pthread_ptr+52>>>2>>>0];var stackSize=GROWABLE_HEAP_U32()[pthread_ptr+56>>>2>>>0];var stackLow=stackHigh-stackSize;assert(stackHigh!=0);assert(stackLow!=0);assert(stackHigh>stackLow,"stackHigh must be higher then stackLow");_emscripten_stack_set_limits(stackHigh,stackLow);stackRestore(stackHigh);writeStackCookie()};var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}assert(wasmTable.get(funcPtr)==func,"JavaScript-side Wasm function table mirror is out of date!");return func};var invokeEntryPoint=(ptr,arg)=>{runtimeKeepaliveCounter=0;noExitRuntime=0;var result=getWasmTableEntry(ptr)(arg);checkStackCookie();function finish(result){if(keepRuntimeAlive()){EXITSTATUS=result}else{__emscripten_thread_exit(result)}}finish(result)};var noExitRuntime=Module["noExitRuntime"]||true;var registerTLSInit=tlsInitFunc=>PThread.tlsInitFunctions.push(tlsInitFunc);var runtimeKeepalivePush=()=>{runtimeKeepaliveCounter+=1};var warnOnce=text=>{warnOnce.shown||={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;if(ENVIRONMENT_IS_NODE)text="warning: "+text;err(text)}};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead=NaN)=>{idx>>>=0;var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.buffer instanceof ArrayBuffer?heapOrArray.subarray(idx,endPtr):heapOrArray.slice(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>{assert(typeof ptr=="number",`UTF8ToString expects a number (got ${typeof ptr})`);ptr>>>=0;return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""};function ___assert_fail(condition,filename,line,func){condition>>>=0;filename>>>=0;func>>>=0;return abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function ___call_sighandler(fp,sig){fp>>>=0;return getWasmTableEntry(fp)(sig)}function pthreadCreateProxied(pthread_ptr,attr,startRoutine,arg){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(2,0,1,pthread_ptr,attr,startRoutine,arg);return ___pthread_create_js(pthread_ptr,attr,startRoutine,arg)}var _emscripten_has_threading_support=()=>typeof SharedArrayBuffer!="undefined";function ___pthread_create_js(pthread_ptr,attr,startRoutine,arg){pthread_ptr>>>=0;attr>>>=0;startRoutine>>>=0;arg>>>=0;if(!_emscripten_has_threading_support()){dbg("pthread_create: environment does not support SharedArrayBuffer, pthreads are not available");return 6}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return pthreadCreateProxied(pthread_ptr,attr,startRoutine,arg)}if(error)return error;var threadParams={startRoutine,pthread_ptr,arg,transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);return 0}return spawnThread(threadParams)}var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>(view.set(crypto.getRandomValues(new Uint8Array(view.byteLength))),view)}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");var randomFillSync=crypto_module["randomFillSync"];if(randomFillSync){return view=>crypto_module["randomFillSync"](view)}var randomBytes=crypto_module["randomBytes"];return view=>(view.set(randomBytes(view.byteLength)),view)}catch(e){}}abort("no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: (array) => { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };")};var randomFill=view=>(randomFill=initRandomFill())(view);var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{outIdx>>>=0;assert(typeof str==="string",`stringToUTF8Array expects a string (got ${typeof str})`);if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++>>>0]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++>>>0]=192|u>>6;heap[outIdx++>>>0]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++>>>0]=224|u>>12;heap[outIdx++>>>0]=128|u>>6&63;heap[outIdx++>>>0]=128|u&63}else{if(outIdx+3>=endIdx)break;if(u>1114111)warnOnce("Invalid Unicode code point "+ptrToString(u)+" encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).");heap[outIdx++>>>0]=240|u>>18;heap[outIdx++>>>0]=128|u>>12&63;heap[outIdx++>>>0]=128|u>>6&63;heap[outIdx++>>>0]=128|u&63}}heap[outIdx>>>0]=0;return outIdx-startIdx};function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;var fd=process.stdin.fd;try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE)}catch(e){if(e.toString().includes("EOF"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output));tty.output=[]}}}};var zeroMemory=(address,size)=>{GROWABLE_HEAP_U8().fill(0,address,address+size)};var alignMemory=(size,alignment)=>{assert(alignment,"alignment argument is required");return Math.ceil(size/alignment)*alignment};var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(ptr)zeroMemory(ptr,size);return ptr};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16895,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.atime=node.mtime=node.ctime=Date.now();if(parent){parent.contents[name]=node;parent.atime=parent.mtime=parent.ctime=node.atime}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.atime);attr.mtime=new Date(node.mtime);attr.ctime=new Date(node.ctime);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){for(const key of["mode","atime","mtime","ctime"]){if(attr[key]){node[key]=attr[key]}}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){throw new FS.ErrnoError(44)},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){if(FS.isDir(old_node.mode)){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}FS.hashRemoveNode(new_node)}delete old_node.parent.contents[old_node.name];new_dir.contents[new_name]=old_node;old_node.name=new_name;new_dir.ctime=new_dir.mtime=old_node.parent.ctime=old_node.parent.mtime=Date.now()},unlink(parent,name){delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},readdir(node){return[".","..",...Object.keys(node.contents)]},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);assert(size>=0);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length>>0)}}return{ptr,allocated}},msync(stream,buffer,offset,length,mmapFlags){MEMFS.stream_ops.write(stream,buffer,0,length,offset,false);return 0}}};var asyncLoad=async url=>{var arrayBuffer=await readAsync(url);assert(arrayBuffer,`Loading data file "${url}" failed (no arrayBuffer).`);return new Uint8Array(arrayBuffer)};var FS_createDataFile=(parent,name,fileData,canRead,canWrite,canOwn)=>{FS.createDataFile(parent,name,fileData,canRead,canWrite,canOwn)};var preloadPlugins=Module["preloadPlugins"]||[];var FS_handledByPreloadPlugin=(byteArray,fullname,finish,onerror)=>{if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(plugin=>{if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}onload?.();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{onerror?.();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url).then(processData,onerror)}else{processData(url)}};var FS_modeStringToFlags=str=>{var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var strError=errno=>UTF8ToString(_strerror(errno));var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:class extends Error{name="ErrnoError";constructor(errno){super(runtimeInitialized?strError(errno):"");this.errno=errno;for(var key in ERRNO_CODES){if(ERRNO_CODES[key]===errno){this.code=key;break}}}},filesystems:null,syncFSRequests:0,readFiles:{},FSStream:class{shared={};get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{node_ops={};stream_ops={};readMode=292|73;writeMode=146;mounted=null;constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.rdev=rdev;this.atime=this.mtime=this.ctime=Date.now()}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){if(!path)return{path:"",node:null};opts.follow_mount??=true;if(!PATH.isAbs(path)){path=FS.cwd()+"/"+path}linkloop:for(var nlinks=0;nlinks<40;nlinks++){var parts=path.split("/").filter(p=>!!p&&p!==".");var current=FS.root;var current_path="/";for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){assert(typeof parent=="object");var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){if(!FS.isDir(dir.mode)){return 54}try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){assert(fd>=-1);stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){assert(FS.syncFSRequests>0);FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount(type,opts,mountpoint){if(typeof type=="string"){throw type}var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type,opts,mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);assert(idx!==-1);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},statfs(path){var rtn={bsize:4096,frsize:4096,blocks:1e6,bfree:5e5,bavail:5e5,files:FS.nextInode,ffree:FS.nextInode-1,fsid:42,flags:2,namelen:255};var parent=FS.lookupPath(path,{follow:true}).node;if(parent?.node_ops.statfs){Object.assign(rtn,parent.node_ops.statfs(parent.mount.opts.root))}return rtn},create(path,mode=438){mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode=511){mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var i=0;i=0);if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){assert(offset>=0);if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate(stream,offset,length){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}if(!length){throw new FS.ErrnoError(28)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){assert(offset>=0);if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error(`Invalid encoding type "${opts.encoding}"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length,llseek:()=>0});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16895,73);node.stream_ops={llseek:MEMFS.stream_ops.llseek};node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path},id:fd+1};ret.parent=ret;return ret},readdir(){return Array.from(FS.streams.entries()).filter(([k,v])=>v).map(([k,v])=>k.toString())}};return node}},{},"/proc/self/fd")},createStandardStreams(input,output,error){if(input){FS.createDevice("/dev","stdin",input)}else{FS.symlink("/dev/tty","/dev/stdin")}if(output){FS.createDevice("/dev","stdout",null,output)}else{FS.symlink("/dev/tty","/dev/stdout")}if(error){FS.createDevice("/dev","stderr",null,error)}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1);assert(stdin.fd===0,`invalid handle for stdin (${stdin.fd})`);assert(stdout.fd===1,`invalid handle for stdout (${stdout.fd})`);assert(stderr.fd===2,`invalid handle for stderr (${stderr.fd})`)},staticInit(){FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS}},init(input,output,error){assert(!FS.initialized,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");FS.initialized=true;input??=Module["stdin"];output??=Module["stdout"];error??=Module["stderr"];FS.createStandardStreams(input,output,error)},quit(){FS.initialized=false;_fflush(0);for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);assert(size>=0);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,GROWABLE_HEAP_I8(),ptr,length,position);return{ptr,allocated:true}};node.stream_ops=stream_ops;return node},absolutePath(){abort("FS.absolutePath has been removed; use PATH_FS.resolve instead")},createFolder(){abort("FS.createFolder has been removed; use FS.mkdir instead")},createLink(){abort("FS.createLink has been removed; use FS.symlink instead")},joinPath(){abort("FS.joinPath has been removed; use PATH.join instead")},mmapAlloc(){abort("FS.mmapAlloc has been replaced by the top level function mmapAlloc")},standardizePath(){abort("FS.standardizePath has been removed; use PATH.normalize instead")}};var SOCKFS={websocketArgs:{},callbacks:{},on(event,callback){SOCKFS.callbacks[event]=callback},emit(event,param){SOCKFS.callbacks[event]?.(param)},mount(mount){SOCKFS.websocketArgs=Module["websocket"]||{};(Module["websocket"]??={})["on"]=SOCKFS.on;return FS.createNode(null,"/",16895,0)},createSocket(family,type,protocol){type&=~526336;var streaming=type==1;if(streaming&&protocol&&protocol!=6){throw new FS.ErrnoError(66)}var sock={family,type,protocol,server:null,error:null,peers:{},pending:[],recv_queue:[],sock_ops:SOCKFS.websocket_sock_ops};var name=SOCKFS.nextname();var node=FS.createNode(SOCKFS.root,name,49152,0);node.sock=sock;var stream=FS.createStream({path:name,node,flags:2,seekable:false,stream_ops:SOCKFS.stream_ops});sock.stream=stream;return sock},getSocket(fd){var stream=FS.getStream(fd);if(!stream||!FS.isSocket(stream.node.mode)){return null}return stream.node.sock},stream_ops:{poll(stream){var sock=stream.node.sock;return sock.sock_ops.poll(sock)},ioctl(stream,request,varargs){var sock=stream.node.sock;return sock.sock_ops.ioctl(sock,request,varargs)},read(stream,buffer,offset,length,position){var sock=stream.node.sock;var msg=sock.sock_ops.recvmsg(sock,length);if(!msg){return 0}buffer.set(msg.buffer,offset);return msg.buffer.length},write(stream,buffer,offset,length,position){var sock=stream.node.sock;return sock.sock_ops.sendmsg(sock,buffer,offset,length)},close(stream){var sock=stream.node.sock;sock.sock_ops.close(sock)}},nextname(){if(!SOCKFS.nextname.current){SOCKFS.nextname.current=0}return`socket[${SOCKFS.nextname.current++}]`},websocket_sock_ops:{createPeer(sock,addr,port){var ws;if(typeof addr=="object"){ws=addr;addr=null;port=null}if(ws){if(ws._socket){addr=ws._socket.remoteAddress;port=ws._socket.remotePort}else{var result=/ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);if(!result){throw new Error("WebSocket URL must be in the format ws(s)://address:port")}addr=result[1];port=parseInt(result[2],10)}}else{try{var url="ws:#".replace("#","//");var subProtocols="binary";var opts=undefined;if(SOCKFS.websocketArgs["url"]){url=SOCKFS.websocketArgs["url"]}if(SOCKFS.websocketArgs["subprotocol"]){subProtocols=SOCKFS.websocketArgs["subprotocol"]}else if(SOCKFS.websocketArgs["subprotocol"]===null){subProtocols="null"}if(url==="ws://"||url==="wss://"){var parts=addr.split("/");url=url+parts[0]+":"+port+"/"+parts.slice(1).join("/")}if(subProtocols!=="null"){subProtocols=subProtocols.replace(/^ +| +$/g,"").split(/ *, */);opts=subProtocols}var WebSocketConstructor;if(ENVIRONMENT_IS_NODE){WebSocketConstructor=require("ws")}else{WebSocketConstructor=WebSocket}ws=new WebSocketConstructor(url,opts);ws.binaryType="arraybuffer"}catch(e){throw new FS.ErrnoError(23)}}var peer={addr,port,socket:ws,msg_send_queue:[]};SOCKFS.websocket_sock_ops.addPeer(sock,peer);SOCKFS.websocket_sock_ops.handlePeerEvents(sock,peer);if(sock.type===2&&typeof sock.sport!="undefined"){peer.msg_send_queue.push(new Uint8Array([255,255,255,255,"p".charCodeAt(0),"o".charCodeAt(0),"r".charCodeAt(0),"t".charCodeAt(0),(sock.sport&65280)>>8,sock.sport&255]))}return peer},getPeer(sock,addr,port){return sock.peers[addr+":"+port]},addPeer(sock,peer){sock.peers[peer.addr+":"+peer.port]=peer},removePeer(sock,peer){delete sock.peers[peer.addr+":"+peer.port]},handlePeerEvents(sock,peer){var first=true;var handleOpen=function(){sock.connecting=false;SOCKFS.emit("open",sock.stream.fd);try{var queued=peer.msg_send_queue.shift();while(queued){peer.socket.send(queued);queued=peer.msg_send_queue.shift()}}catch(e){peer.socket.close()}};function handleMessage(data){if(typeof data=="string"){var encoder=new TextEncoder;data=encoder.encode(data)}else{assert(data.byteLength!==undefined);if(data.byteLength==0){return}data=new Uint8Array(data)}var wasfirst=first;first=false;if(wasfirst&&data.length===10&&data[0]===255&&data[1]===255&&data[2]===255&&data[3]===255&&data[4]==="p".charCodeAt(0)&&data[5]==="o".charCodeAt(0)&&data[6]==="r".charCodeAt(0)&&data[7]==="t".charCodeAt(0)){var newport=data[8]<<8|data[9];SOCKFS.websocket_sock_ops.removePeer(sock,peer);peer.port=newport;SOCKFS.websocket_sock_ops.addPeer(sock,peer);return}sock.recv_queue.push({addr:peer.addr,port:peer.port,data});SOCKFS.emit("message",sock.stream.fd)}if(ENVIRONMENT_IS_NODE){peer.socket.on("open",handleOpen);peer.socket.on("message",function(data,isBinary){if(!isBinary){return}handleMessage(new Uint8Array(data).buffer)});peer.socket.on("close",function(){SOCKFS.emit("close",sock.stream.fd)});peer.socket.on("error",function(error){sock.error=14;SOCKFS.emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])})}else{peer.socket.onopen=handleOpen;peer.socket.onclose=function(){SOCKFS.emit("close",sock.stream.fd)};peer.socket.onmessage=function peer_socket_onmessage(event){handleMessage(event.data)};peer.socket.onerror=function(error){sock.error=14;SOCKFS.emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])}}},poll(sock){if(sock.type===1&&sock.server){return sock.pending.length?64|1:0}var mask=0;var dest=sock.type===1?SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport):null;if(sock.recv_queue.length||!dest||dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=64|1}if(!dest||dest&&dest.socket.readyState===dest.socket.OPEN){mask|=4}if(dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){if(sock.connecting){mask|=4}else{mask|=16}}return mask},ioctl(sock,request,arg){switch(request){case 21531:var bytes=0;if(sock.recv_queue.length){bytes=sock.recv_queue[0].data.length}GROWABLE_HEAP_I32()[arg>>>2>>>0]=bytes;return 0;default:return 28}},close(sock){if(sock.server){try{sock.server.close()}catch(e){}sock.server=null}var peers=Object.keys(sock.peers);for(var i=0;i{var socket=SOCKFS.getSocket(fd);if(!socket)throw new FS.ErrnoError(8);return socket};var inetPton4=str=>{var b=str.split(".");for(var i=0;i<4;i++){var tmp=Number(b[i]);if(isNaN(tmp))return null;b[i]=tmp}return(b[0]|b[1]<<8|b[2]<<16|b[3]<<24)>>>0};var jstoi_q=str=>parseInt(str);var inetPton6=str=>{var words;var w,offset,z;var valid6regx=/^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;var parts=[];if(!valid6regx.test(str)){return null}if(str==="::"){return[0,0,0,0,0,0,0,0]}if(str.startsWith("::")){str=str.replace("::","Z:")}else{str=str.replace("::",":Z:")}if(str.indexOf(".")>0){str=str.replace(new RegExp("[.]","g"),":");words=str.split(":");words[words.length-4]=jstoi_q(words[words.length-4])+jstoi_q(words[words.length-3])*256;words[words.length-3]=jstoi_q(words[words.length-2])+jstoi_q(words[words.length-1])*256;words=words.slice(0,words.length-2)}else{words=str.split(":")}offset=0;z=0;for(w=0;w{switch(family){case 2:addr=inetPton4(addr);zeroMemory(sa,16);if(addrlen){GROWABLE_HEAP_I32()[addrlen>>>2>>>0]=16}GROWABLE_HEAP_I16()[sa>>>1>>>0]=family;GROWABLE_HEAP_I32()[sa+4>>>2>>>0]=addr;GROWABLE_HEAP_I16()[sa+2>>>1>>>0]=_htons(port);break;case 10:addr=inetPton6(addr);zeroMemory(sa,28);if(addrlen){GROWABLE_HEAP_I32()[addrlen>>>2>>>0]=28}GROWABLE_HEAP_I32()[sa>>>2>>>0]=family;GROWABLE_HEAP_I32()[sa+8>>>2>>>0]=addr[0];GROWABLE_HEAP_I32()[sa+12>>>2>>>0]=addr[1];GROWABLE_HEAP_I32()[sa+16>>>2>>>0]=addr[2];GROWABLE_HEAP_I32()[sa+20>>>2>>>0]=addr[3];GROWABLE_HEAP_I16()[sa+2>>>1>>>0]=_htons(port);break;default:return 5}return 0};var DNS={address_map:{id:1,addrs:{},names:{}},lookup_name(name){var res=inetPton4(name);if(res!==null){return name}res=inetPton6(name);if(res!==null){return name}var addr;if(DNS.address_map.addrs[name]){addr=DNS.address_map.addrs[name]}else{var id=DNS.address_map.id++;assert(id<65535,"exceeded max address mappings of 65535");addr="172.29."+(id&255)+"."+(id&65280);DNS.address_map.names[addr]=name;DNS.address_map.addrs[name]=addr}return addr},lookup_addr(addr){if(DNS.address_map.names[addr]){return DNS.address_map.names[addr]}return null}};function ___syscall_accept4(fd,addr,addrlen,flags,d1,d2){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(3,0,1,fd,addr,addrlen,flags,d1,d2);addr>>>=0;addrlen>>>=0;try{var sock=getSocketFromFD(fd);var newsock=sock.sock_ops.accept(sock);if(addr){var errno=writeSockaddr(addr,newsock.family,DNS.lookup_name(newsock.daddr),newsock.dport,addrlen);assert(!errno)}return newsock.stream.fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var inetNtop4=addr=>(addr&255)+"."+(addr>>8&255)+"."+(addr>>16&255)+"."+(addr>>24&255);var inetNtop6=ints=>{var str="";var word=0;var longest=0;var lastzero=0;var zstart=0;var len=0;var i=0;var parts=[ints[0]&65535,ints[0]>>16,ints[1]&65535,ints[1]>>16,ints[2]&65535,ints[2]>>16,ints[3]&65535,ints[3]>>16];var hasipv4=true;var v4part="";for(i=0;i<5;i++){if(parts[i]!==0){hasipv4=false;break}}if(hasipv4){v4part=inetNtop4(parts[6]|parts[7]<<16);if(parts[5]===-1){str="::ffff:";str+=v4part;return str}if(parts[5]===0){str="::";if(v4part==="0.0.0.0")v4part="";if(v4part==="0.0.0.1")v4part="1";str+=v4part;return str}}for(word=0;word<8;word++){if(parts[word]===0){if(word-lastzero>1){len=0}lastzero=word;len++}if(len>longest){longest=len;zstart=word-longest+1}}for(word=0;word<8;word++){if(longest>1){if(parts[word]===0&&word>=zstart&&word{var family=GROWABLE_HEAP_I16()[sa>>>1>>>0];var port=_ntohs(GROWABLE_HEAP_U16()[sa+2>>>1>>>0]);var addr;switch(family){case 2:if(salen!==16){return{errno:28}}addr=GROWABLE_HEAP_I32()[sa+4>>>2>>>0];addr=inetNtop4(addr);break;case 10:if(salen!==28){return{errno:28}}addr=[GROWABLE_HEAP_I32()[sa+8>>>2>>>0],GROWABLE_HEAP_I32()[sa+12>>>2>>>0],GROWABLE_HEAP_I32()[sa+16>>>2>>>0],GROWABLE_HEAP_I32()[sa+20>>>2>>>0]];addr=inetNtop6(addr);break;default:return{errno:5}}return{family,addr,port}};var getSocketAddress=(addrp,addrlen)=>{var info=readSockaddr(addrp,addrlen);if(info.errno)throw new FS.ErrnoError(info.errno);info.addr=DNS.lookup_addr(info.addr)||info.addr;return info};function ___syscall_bind(fd,addr,addrlen,d1,d2,d3){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(4,0,1,fd,addr,addrlen,d1,d2,d3);addr>>>=0;addrlen>>>=0;try{var sock=getSocketFromFD(fd);var info=getSocketAddress(addr,addrlen);sock.sock_ops.bind(sock,info.addr,info.port);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return dir+"/"+path},doStat(func,path,buf){var stat=func(path);GROWABLE_HEAP_I32()[buf>>>2>>>0]=stat.dev;GROWABLE_HEAP_I32()[buf+4>>>2>>>0]=stat.mode;GROWABLE_HEAP_U32()[buf+8>>>2>>>0]=stat.nlink;GROWABLE_HEAP_I32()[buf+12>>>2>>>0]=stat.uid;GROWABLE_HEAP_I32()[buf+16>>>2>>>0]=stat.gid;GROWABLE_HEAP_I32()[buf+20>>>2>>>0]=stat.rdev;HEAP64[buf+24>>>3]=BigInt(stat.size);GROWABLE_HEAP_I32()[buf+32>>>2>>>0]=4096;GROWABLE_HEAP_I32()[buf+36>>>2>>>0]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();HEAP64[buf+40>>>3]=BigInt(Math.floor(atime/1e3));GROWABLE_HEAP_U32()[buf+48>>>2>>>0]=atime%1e3*1e3*1e3;HEAP64[buf+56>>>3]=BigInt(Math.floor(mtime/1e3));GROWABLE_HEAP_U32()[buf+64>>>2>>>0]=mtime%1e3*1e3*1e3;HEAP64[buf+72>>>3]=BigInt(Math.floor(ctime/1e3));GROWABLE_HEAP_U32()[buf+80>>>2>>>0]=ctime%1e3*1e3*1e3;HEAP64[buf+88>>>3]=BigInt(stat.ino);return 0},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=GROWABLE_HEAP_U8().slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_chdir(path){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(5,0,1,path);path>>>=0;try{path=SYSCALLS.getStr(path);FS.chdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_chmod(path,mode){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(6,0,1,path,mode);path>>>=0;try{path=SYSCALLS.getStr(path);FS.chmod(path,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_connect(fd,addr,addrlen,d1,d2,d3){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(7,0,1,fd,addr,addrlen,d1,d2,d3);addr>>>=0;addrlen>>>=0;try{var sock=getSocketFromFD(fd);var info=getSocketAddress(addr,addrlen);sock.sock_ops.connect(sock,info.addr,info.port);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_dup(fd){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(8,0,1,fd);try{var old=SYSCALLS.getStreamFromFD(fd);return FS.dupStream(old).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_dup3(fd,newfd,flags){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(9,0,1,fd,newfd,flags);try{var old=SYSCALLS.getStreamFromFD(fd);assert(!flags);if(old.fd===newfd)return-28;if(newfd<0||newfd>=FS.MAX_OPEN_FDS)return-8;var existing=FS.getStream(newfd);if(existing)FS.close(existing);return FS.dupStream(old,newfd).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_faccessat(dirfd,path,amode,flags){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(10,0,1,dirfd,path,amode,flags);path>>>=0;try{path=SYSCALLS.getStr(path);assert(flags===0||flags==512);path=SYSCALLS.calculateAt(dirfd,path);if(amode&~7){return-28}var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchmodat2(dirfd,path,mode,flags){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(11,0,1,dirfd,path,mode,flags);path>>>=0;try{var nofollow=flags&256;path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);FS.chmod(path,mode,nofollow);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchownat(dirfd,path,owner,group,flags){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(12,0,1,dirfd,path,owner,group,flags);path>>>=0;try{path=SYSCALLS.getStr(path);var nofollow=flags&256;flags=flags&~256;assert(flags===0);path=SYSCALLS.calculateAt(dirfd,path);(nofollow?FS.lchown:FS.chown)(path,owner,group);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var syscallGetVarargI=()=>{assert(SYSCALLS.varargs!=undefined);var ret=GROWABLE_HEAP_I32()[+SYSCALLS.varargs>>>2>>>0];SYSCALLS.varargs+=4;return ret};var syscallGetVarargP=syscallGetVarargI;function ___syscall_fcntl64(fd,cmd,varargs){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(13,0,1,fd,cmd,varargs);varargs>>>=0;SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 12:{var arg=syscallGetVarargP();var offset=0;GROWABLE_HEAP_I16()[arg+offset>>>1>>>0]=2;return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(14,0,1,fd,buf);buf>>>=0;try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ftruncate64(fd,length){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(15,0,1,fd,length);length=bigintToI53Checked(length);try{if(isNaN(length))return 61;FS.ftruncate(fd,length);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>{assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)};function ___syscall_getcwd(buf,size){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(16,0,1,buf,size);buf>>>=0;size>>>=0;try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd)+1;if(size>>=0;count>>>=0;try{var stream=SYSCALLS.getStreamFromFD(fd);stream.getdents||=FS.readdir(stream.path);var struct_size=280;var pos=0;var off=FS.llseek(stream,0,1);var startIdx=Math.floor(off/struct_size);var endIdx=Math.min(stream.getdents.length,startIdx+Math.floor(count/struct_size));for(var idx=startIdx;idx>>3]=BigInt(id);HEAP64[dirp+pos+8>>>3]=BigInt((idx+1)*struct_size);GROWABLE_HEAP_I16()[dirp+pos+16>>>1>>>0]=280;GROWABLE_HEAP_I8()[dirp+pos+18>>>0]=type;stringToUTF8(name,dirp+pos+19,256);pos+=struct_size}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getpeername(fd,addr,addrlen,d1,d2,d3){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(18,0,1,fd,addr,addrlen,d1,d2,d3);addr>>>=0;addrlen>>>=0;try{var sock=getSocketFromFD(fd);if(!sock.daddr){return-53}var errno=writeSockaddr(addr,sock.family,DNS.lookup_name(sock.daddr),sock.dport,addrlen);assert(!errno);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getsockname(fd,addr,addrlen,d1,d2,d3){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(19,0,1,fd,addr,addrlen,d1,d2,d3);addr>>>=0;addrlen>>>=0;try{var sock=getSocketFromFD(fd);var errno=writeSockaddr(addr,sock.family,DNS.lookup_name(sock.saddr||"0.0.0.0"),sock.sport,addrlen);assert(!errno);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getsockopt(fd,level,optname,optval,optlen,d1){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(20,0,1,fd,level,optname,optval,optlen,d1);optval>>>=0;optlen>>>=0;try{var sock=getSocketFromFD(fd);if(level===1){if(optname===4){GROWABLE_HEAP_I32()[optval>>>2>>>0]=sock.error;GROWABLE_HEAP_I32()[optlen>>>2>>>0]=4;sock.error=null;return 0}}return-50}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(21,0,1,fd,op,varargs);varargs>>>=0;SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();GROWABLE_HEAP_I32()[argp>>>2>>>0]=termios.c_iflag||0;GROWABLE_HEAP_I32()[argp+4>>>2>>>0]=termios.c_oflag||0;GROWABLE_HEAP_I32()[argp+8>>>2>>>0]=termios.c_cflag||0;GROWABLE_HEAP_I32()[argp+12>>>2>>>0]=termios.c_lflag||0;for(var i=0;i<32;i++){GROWABLE_HEAP_I8()[argp+i+17>>>0]=termios.c_cc[i]||0}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=GROWABLE_HEAP_I32()[argp>>>2>>>0];var c_oflag=GROWABLE_HEAP_I32()[argp+4>>>2>>>0];var c_cflag=GROWABLE_HEAP_I32()[argp+8>>>2>>>0];var c_lflag=GROWABLE_HEAP_I32()[argp+12>>>2>>>0];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(GROWABLE_HEAP_I8()[argp+i+17>>>0])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag,c_oflag,c_cflag,c_lflag,c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();GROWABLE_HEAP_I32()[argp>>>2>>>0]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();GROWABLE_HEAP_I16()[argp>>>1>>>0]=winsize[0];GROWABLE_HEAP_I16()[argp+2>>>1>>>0]=winsize[1]}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_listen(fd,backlog){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(22,0,1,fd,backlog);try{var sock=getSocketFromFD(fd);sock.sock_ops.listen(sock,backlog);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(23,0,1,path,buf);path>>>=0;buf>>>=0;try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(24,0,1,dirfd,path,mode);path>>>=0;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(25,0,1,dirfd,path,buf,flags);path>>>=0;buf>>>=0;try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;assert(!flags,`unknown flags in __syscall_newfstatat: ${flags}`);path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(26,0,1,dirfd,path,flags,varargs);path>>>=0;varargs>>>=0;SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var PIPEFS={BUCKET_BUFFER_SIZE:8192,mount(mount){return FS.createNode(null,"/",16384|511,0)},createPipe(){var pipe={buckets:[],refcnt:2};pipe.buckets.push({buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:0,roffset:0});var rName=PIPEFS.nextname();var wName=PIPEFS.nextname();var rNode=FS.createNode(PIPEFS.root,rName,4096,0);var wNode=FS.createNode(PIPEFS.root,wName,4096,0);rNode.pipe=pipe;wNode.pipe=pipe;var readableStream=FS.createStream({path:rName,node:rNode,flags:0,seekable:false,stream_ops:PIPEFS.stream_ops});rNode.stream=readableStream;var writableStream=FS.createStream({path:wName,node:wNode,flags:1,seekable:false,stream_ops:PIPEFS.stream_ops});wNode.stream=writableStream;return{readable_fd:readableStream.fd,writable_fd:writableStream.fd}},stream_ops:{poll(stream){var pipe=stream.node.pipe;if((stream.flags&2097155)===1){return 256|4}if(pipe.buckets.length>0){for(var i=0;i0){return 64|1}}}return 0},ioctl(stream,request,varargs){return 28},fsync(stream){return 28},read(stream,buffer,offset,length,position){var pipe=stream.node.pipe;var currentLength=0;for(var i=0;i=dataLen){currBucket.buffer.set(data,currBucket.offset);currBucket.offset+=dataLen;return dataLen}else if(freeBytesInCurrBuffer>0){currBucket.buffer.set(data.subarray(0,freeBytesInCurrBuffer),currBucket.offset);currBucket.offset+=freeBytesInCurrBuffer;data=data.subarray(freeBytesInCurrBuffer,data.byteLength)}var numBuckets=data.byteLength/PIPEFS.BUCKET_BUFFER_SIZE|0;var remElements=data.byteLength%PIPEFS.BUCKET_BUFFER_SIZE;for(var i=0;i0){var newBucket={buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:data.byteLength,roffset:0};pipe.buckets.push(newBucket);newBucket.buffer.set(data)}return dataLen},close(stream){var pipe=stream.node.pipe;pipe.refcnt--;if(pipe.refcnt===0){pipe.buckets=null}}},nextname(){if(!PIPEFS.nextname.current){PIPEFS.nextname.current=0}return"pipe["+PIPEFS.nextname.current+++"]"}};function ___syscall_pipe(fdPtr){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(27,0,1,fdPtr);fdPtr>>>=0;try{if(fdPtr==0){throw new FS.ErrnoError(21)}var res=PIPEFS.createPipe();GROWABLE_HEAP_I32()[fdPtr>>>2>>>0]=res.readable_fd;GROWABLE_HEAP_I32()[fdPtr+4>>>2>>>0]=res.writable_fd;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_poll(fds,nfds,timeout){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(28,0,1,fds,nfds,timeout);fds>>>=0;try{var nonzero=0;for(var i=0;i>>2>>>0];var events=GROWABLE_HEAP_I16()[pollfd+4>>>1>>>0];var mask=32;var stream=FS.getStream(fd);if(stream){mask=SYSCALLS.DEFAULT_POLLMASK;if(stream.stream_ops.poll){mask=stream.stream_ops.poll(stream,-1)}}mask&=events|8|16;if(mask)nonzero++;GROWABLE_HEAP_I16()[pollfd+6>>>1>>>0]=mask}return nonzero}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_readlinkat(dirfd,path,buf,bufsize){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(29,0,1,dirfd,path,buf,bufsize);path>>>=0;buf>>>=0;bufsize>>>=0;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=GROWABLE_HEAP_I8()[buf+len>>>0];stringToUTF8(ret,buf,bufsize+1);GROWABLE_HEAP_I8()[buf+len>>>0]=endChar;return len}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_recvfrom(fd,buf,len,flags,addr,addrlen){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(30,0,1,fd,buf,len,flags,addr,addrlen);buf>>>=0;len>>>=0;addr>>>=0;addrlen>>>=0;try{var sock=getSocketFromFD(fd);var msg=sock.sock_ops.recvmsg(sock,len);if(!msg)return 0;if(addr){var errno=writeSockaddr(addr,sock.family,DNS.lookup_name(msg.addr),msg.port,addrlen);assert(!errno)}GROWABLE_HEAP_U8().set(msg.buffer,buf>>>0);return msg.buffer.byteLength}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_renameat(olddirfd,oldpath,newdirfd,newpath){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(31,0,1,olddirfd,oldpath,newdirfd,newpath);oldpath>>>=0;newpath>>>=0;try{oldpath=SYSCALLS.getStr(oldpath);newpath=SYSCALLS.getStr(newpath);oldpath=SYSCALLS.calculateAt(olddirfd,oldpath);newpath=SYSCALLS.calculateAt(newdirfd,newpath);FS.rename(oldpath,newpath);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_rmdir(path){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(32,0,1,path);path>>>=0;try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_sendto(fd,message,length,flags,addr,addr_len){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(33,0,1,fd,message,length,flags,addr,addr_len);message>>>=0;length>>>=0;addr>>>=0;addr_len>>>=0;try{var sock=getSocketFromFD(fd);if(!addr){return FS.write(sock.stream,GROWABLE_HEAP_I8(),message,length)}var dest=getSocketAddress(addr,addr_len);return sock.sock_ops.sendmsg(sock,GROWABLE_HEAP_I8(),message,length,dest.addr,dest.port)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_socket(domain,type,protocol){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(34,0,1,domain,type,protocol);try{var sock=SOCKFS.createSocket(domain,type,protocol);assert(sock.stream.fd<64);return sock.stream.fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(35,0,1,path,buf);path>>>=0;buf>>>=0;try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_symlinkat(target,dirfd,linkpath){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(36,0,1,target,dirfd,linkpath);target>>>=0;linkpath>>>=0;try{target=SYSCALLS.getStr(target);linkpath=SYSCALLS.getStr(linkpath);linkpath=SYSCALLS.calculateAt(dirfd,linkpath);FS.symlink(target,linkpath);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_unlinkat(dirfd,path,flags){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(37,0,1,dirfd,path,flags);path>>>=0;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(flags===0){FS.unlink(path)}else if(flags===512){FS.rmdir(path)}else{abort("Invalid flags passed to unlinkat")}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var readI53FromI64=ptr=>GROWABLE_HEAP_U32()[ptr>>>2>>>0]+GROWABLE_HEAP_I32()[ptr+4>>>2>>>0]*4294967296;function ___syscall_utimensat(dirfd,path,times,flags){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(38,0,1,dirfd,path,times,flags);path>>>=0;times>>>=0;try{path=SYSCALLS.getStr(path);assert(flags===0);path=SYSCALLS.calculateAt(dirfd,path,true);var now=Date.now(),atime,mtime;if(!times){atime=now;mtime=now}else{var seconds=readI53FromI64(times);var nanoseconds=GROWABLE_HEAP_I32()[times+8>>>2>>>0];if(nanoseconds==1073741823){atime=now}else if(nanoseconds==1073741822){atime=null}else{atime=seconds*1e3+nanoseconds/(1e3*1e3)}times+=16;seconds=readI53FromI64(times);nanoseconds=GROWABLE_HEAP_I32()[times+8>>>2>>>0];if(nanoseconds==1073741823){mtime=now}else if(nanoseconds==1073741822){mtime=null}else{mtime=seconds*1e3+nanoseconds/(1e3*1e3)}}if((mtime??atime)!==null){FS.utime(path,atime,mtime)}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var getCppExceptionTag=()=>wasmExports["__cpp_exception"];var getCppExceptionThrownObjectFromWebAssemblyException=ex=>{var unwind_header=ex.getArg(getCppExceptionTag(),0);return ___thrown_object_from_unwind_exception(unwind_header)};var getExceptionMessageCommon=ptr=>{var sp=stackSave();var type_addr_addr=stackAlloc(4);var message_addr_addr=stackAlloc(4);___get_exception_message(ptr,type_addr_addr,message_addr_addr);var type_addr=GROWABLE_HEAP_U32()[type_addr_addr>>>2>>>0];var message_addr=GROWABLE_HEAP_U32()[message_addr_addr>>>2>>>0];var type=UTF8ToString(type_addr);_free(type_addr);var message;if(message_addr){message=UTF8ToString(message_addr);_free(message_addr)}stackRestore(sp);return[type,message]};var getExceptionMessage=ex=>{var ptr=getCppExceptionThrownObjectFromWebAssemblyException(ex);return getExceptionMessageCommon(ptr)};Module["getExceptionMessage"]=getExceptionMessage;var ___throw_exception_with_stack_trace=ex=>{var e=new WebAssembly.Exception(getCppExceptionTag(),[ex],{traceStack:true});e.message=getExceptionMessage(e);throw e};var __abort_js=()=>abort("native code called abort()");var createNamedFunction=(name,body)=>Object.defineProperty(body,"name",{value:name});var emval_freelist=[];var emval_handles=[];var BindingError;var throwBindingError=message=>{throw new BindingError(message)};var count_emval_handles=()=>emval_handles.length/2-5-emval_freelist.length;var init_emval=()=>{emval_handles.push(0,1,undefined,1,null,1,true,1,false,1);assert(emval_handles.length===5*2);Module["count_emval_handles"]=count_emval_handles};var Emval={toValue:handle=>{if(!handle){throwBindingError("Cannot use deleted val. handle = "+handle)}assert(handle===2||emval_handles[handle]!==undefined&&handle%2===0,`invalid handle: ${handle}`);return emval_handles[handle]},toHandle:value=>{switch(value){case undefined:return 2;case null:return 4;case true:return 6;case false:return 8;default:{const handle=emval_freelist.pop()||emval_handles.length;emval_handles[handle]=value;emval_handles[handle+1]=1;return handle}}}};var extendError=(baseErrorType,errorName)=>{var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return`${this.name}: ${this.message}`}};return errorClass};var PureVirtualError;var embind_init_charCodes=()=>{var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes};var embind_charCodes;var readLatin1String=ptr=>{var ret="";var c=ptr;while(GROWABLE_HEAP_U8()[c>>>0]){ret+=embind_charCodes[GROWABLE_HEAP_U8()[c++>>>0]]}return ret};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var registerInheritedInstance=(class_,ptr,instance)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){throwBindingError(`Tried to register registered instance: ${ptr}`)}else{registeredInstances[ptr]=instance}};var registeredTypes={};var getTypeName=type=>{var ptr=___getTypeName(type);var rv=readLatin1String(ptr);_free(ptr);return rv};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`)}return impl};var unregisterInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);if(registeredInstances.hasOwnProperty(ptr)){delete registeredInstances[ptr]}else{throwBindingError(`Tried to unregister unregistered instance: ${ptr}`)}};var detachFinalizer=handle=>{};var finalizationRegistry=false;var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var registeredPointers={};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var InternalError;var throwInternalError=message=>{throw new InternalError(message)};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record,writable:true}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var attachFinalizer=handle=>{if("undefined"===typeof FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{console.warn(info.leakWarning);releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$};var cls=$$.ptrType.registeredClass;var err=new Error(`Embind found a leaked C++ instance ${cls.name} <${ptrToString($$.ptr)}>.\n`+"We'll free it automatically in this case, but this functionality is not reliable across various environments.\n"+"Make sure to invoke .delete() manually once you're done with the instance instead.\n"+"Originally allocated");if("captureStackTrace"in Error){Error.captureStackTrace(err,RegisteredPointer_fromWireType)}info.leakWarning=err.stack.replace(/^Error: /,"");finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};function __embind_create_inheriting_constructor(constructorName,wrapperType,properties){constructorName>>>=0;wrapperType>>>=0;properties>>>=0;constructorName=readLatin1String(constructorName);wrapperType=requireRegisteredType(wrapperType,"wrapper");properties=Emval.toValue(properties);var registeredClass=wrapperType.registeredClass;var wrapperPrototype=registeredClass.instancePrototype;var baseClass=registeredClass.baseClass;var baseClassPrototype=baseClass.instancePrototype;var baseConstructor=registeredClass.baseClass.constructor;var ctor=createNamedFunction(constructorName,function(...args){registeredClass.baseClass.pureVirtualFunctions.forEach(function(name){if(this[name]===baseClassPrototype[name]){throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`)}}.bind(this));Object.defineProperty(this,"__parent",{value:wrapperPrototype});this["__construct"](...args)});wrapperPrototype["__construct"]=function __construct(...args){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __construct")}var inner=baseConstructor["implement"](this,...args);detachFinalizer(inner);var $$=inner.$$;inner["notifyOnDestruction"]();$$.preservePointerOnDelete=true;Object.defineProperties(this,{$$:{value:$$}});attachFinalizer(this);registerInheritedInstance(registeredClass,$$.ptr,this)};wrapperPrototype["__destruct"]=function __destruct(){if(this===wrapperPrototype){throwBindingError("Pass correct 'this' to __destruct")}detachFinalizer(this);unregisterInheritedInstance(registeredClass,this.$$.ptr)};ctor.prototype=Object.create(wrapperPrototype);Object.assign(ctor.prototype,properties);return Emval.toHandle(ctor)}var structRegistrations={};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function readPointer(pointer){return this["fromWireType"](GROWABLE_HEAP_U32()[pointer>>>2>>>0])}var awaitingDependencies={};var typeDependencies={};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(type=>typeDependencies[type]=dependentTypes);function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{if(registeredTypes.hasOwnProperty(dt)){typeConverters[i]=registeredTypes[dt]}else{unregisteredTypes.push(dt);if(!awaitingDependencies.hasOwnProperty(dt)){awaitingDependencies[dt]=[]}awaitingDependencies[dt].push(()=>{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}});if(0===unregisteredTypes.length){onComplete(typeConverters)}};var __embind_finalize_value_object=function(structType){structType>>>=0;var reg=structRegistrations[structType];delete structRegistrations[structType];var rawConstructor=reg.rawConstructor;var rawDestructor=reg.rawDestructor;var fieldRecords=reg.fields;var fieldTypes=fieldRecords.map(field=>field.getterReturnType).concat(fieldRecords.map(field=>field.setterArgumentType));whenDependentTypesAreResolved([structType],fieldTypes,fieldTypes=>{var fields={};fieldRecords.forEach((field,i)=>{var fieldName=field.fieldName;var getterReturnType=fieldTypes[i];var getter=field.getter;var getterContext=field.getterContext;var setterArgumentType=fieldTypes[i+fieldRecords.length];var setter=field.setter;var setterContext=field.setterContext;fields[fieldName]={read:ptr=>getterReturnType["fromWireType"](getter(getterContext,ptr)),write:(ptr,o)=>{var destructors=[];setter(setterContext,ptr,setterArgumentType["toWireType"](destructors,o));runDestructors(destructors)}}});return[{name:reg.name,fromWireType:ptr=>{var rv={};for(var i in fields){rv[i]=fields[i].read(ptr)}rawDestructor(ptr);return rv},toWireType:(destructors,o)=>{for(var fieldName in fields){if(!(fieldName in o)){throw new TypeError(`Missing field: "${fieldName}"`)}}var ptr=rawConstructor();for(fieldName in fields){fields[fieldName].write(ptr,o[fieldName])}if(destructors!==null){destructors.push(rawDestructor,ptr)}return ptr},argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,destructorFunction:rawDestructor}]})};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){if(registeredInstance.argPackAdvance===undefined){throw new TypeError("registerType registeredInstance requires argPackAdvance")}return sharedRegisterType(rawType,registeredInstance,options)}var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>GROWABLE_HEAP_I8()[pointer>>>0]:pointer=>GROWABLE_HEAP_U8()[pointer>>>0];case 2:return signed?pointer=>GROWABLE_HEAP_I16()[pointer>>>1>>>0]:pointer=>GROWABLE_HEAP_U16()[pointer>>>1>>>0];case 4:return signed?pointer=>GROWABLE_HEAP_I32()[pointer>>>2>>>0]:pointer=>GROWABLE_HEAP_U32()[pointer>>>2>>>0];case 8:return signed?pointer=>HEAP64[pointer>>>3]:pointer=>HEAPU64[pointer>>>3];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};function __embind_register_bigint(primitiveType,name,size,minRange,maxRange){primitiveType>>>=0;name>>>=0;size>>>=0;name=readLatin1String(name);var isUnsignedType=name.indexOf("u")!=-1;if(isUnsignedType){maxRange=(1n<<64n)-1n}registerType(primitiveType,{name,fromWireType:value=>value,toWireType:function(destructors,value){if(typeof value!="bigint"&&typeof value!="number"){throw new TypeError(`Cannot convert "${embindRepr(value)}" to ${this.name}`)}if(typeof value=="number"){value=BigInt(value)}if(valuemaxRange){throw new TypeError(`Passing a number "${embindRepr(value)}" from JS side to C/C++ side to an argument of type "${name}", which is outside the valid range [${minRange}, ${maxRange}]!`)}return value},argPackAdvance:GenericWireTypeSize,readValueFromPointer:integerReadValueFromPointer(name,size,!isUnsignedType),destructorFunction:null})}var GenericWireTypeSize=8;function __embind_register_bool(rawType,name,trueValue,falseValue){rawType>>>=0;name>>>=0;name=readLatin1String(name);registerType(rawType,{name,fromWireType:function(wt){return!!wt},toWireType:function(destructors,o){return o?trueValue:falseValue},argPackAdvance:GenericWireTypeSize,readValueFromPointer:function(pointer){return this["fromWireType"](GROWABLE_HEAP_U8()[pointer>>>0])},destructorFunction:null})}var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction;var init_ClassHandle=()=>{Object.assign(ClassHandle.prototype,{isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;other.$$=other.$$;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right},clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}},delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}},isDeleted(){return!this.$$.ptr},deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}})};function ClassHandle(){}var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(...args){if(!proto[methodName].overloadTable.hasOwnProperty(args.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[args.length].apply(this,args)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module[name].overloadTable.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{assert(typeof name==="string");name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle||!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}var init_RegisteredPointer=()=>{Object.assign(RegisteredPointer.prototype,{getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr},destructor(ptr){this.rawDestructor?.(ptr)},argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,fromWireType:RegisteredPointer_fromWireType})};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistent public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var dynCall=(sig,ptr,args=[])=>{assert(getWasmTableEntry(ptr),`missing table entry in dynCall: ${ptr}`);var rtn=getWasmTableEntry(ptr)(...args);return sig[0]=="p"?rtn>>>0:rtn};var getDynCaller=(sig,ptr)=>{assert(sig.includes("j")||sig.includes("p"),"getDynCaller should only be called with i64 sigs");return(...args)=>dynCall(sig,ptr,args)};var embind__requireFunction=(signature,rawFunction)=>{signature=readLatin1String(signature);function makeDynCaller(){if(signature.includes("p")){return getDynCaller(signature,rawFunction)}return getWasmTableEntry(rawFunction)}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};var UnboundTypeError;var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};function __embind_register_class(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor){rawType>>>=0;rawPointerType>>>=0;rawConstPointerType>>>=0;baseClassRawType>>>=0;getActualTypeSignature>>>=0;getActualType>>>=0;upcastSignature>>>=0;upcast>>>=0;downcastSignature>>>=0;downcast>>>=0;name>>>=0;destructorSignature>>>=0;rawDestructor>>>=0;name=readLatin1String(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);upcast&&=embind__requireFunction(upcastSignature,upcast);downcast&&=embind__requireFunction(downcastSignature,downcast);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],base=>{base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(name,function(...args){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError("Use 'new' to construct "+name)}if(undefined===registeredClass.constructor_body){throw new BindingError(name+" has no accessible constructor")}var body=registeredClass.constructor_body[args.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,args)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){registeredClass.baseClass.__derivedClasses??=[];registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})}function usesDestructorStack(argTypes){for(var i=1;imaxArgs){var argCountMessage=minArgs==maxArgs?minArgs:`${minArgs} to ${maxArgs}`;throwBindingError(`function ${humanName} called with ${numArgs} arguments, expected ${argCountMessage}`)}}function createJsInvoker(argTypes,isClassMethodFunc,returns,isAsync){var needsDestructorStack=usesDestructorStack(argTypes);var argCount=argTypes.length-2;var argsList=[];var argsListWired=["fn"];if(isClassMethodFunc){argsListWired.push("thisWired")}for(var i=0;i=2;--i){if(!argTypes[i].optional){break}requiredArgCount--}return requiredArgCount}function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFunc,cppTargetFunc,isAsync){var argCount=argTypes.length;if(argCount<2){throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!")}assert(!isAsync,"Async bindings are only supported with JSPI.");var isClassMethodFunc=argTypes[1]!==null&&classType!==null;var needsDestructorStack=usesDestructorStack(argTypes);var returns=argTypes[0].name!=="void";var expectedArgCount=argCount-2;var minArgs=getRequiredArgCount(argTypes);var closureArgs=[humanName,throwBindingError,cppInvokerFunc,cppTargetFunc,runDestructors,argTypes[0],argTypes[1]];for(var i=0;i{var array=[];for(var i=0;i>>2>>>0])}return array};var getFunctionName=signature=>{signature=signature.trim();const argsIndex=signature.indexOf("(");if(argsIndex!==-1){assert(signature[signature.length-1]==")","Parentheses for argument names should match.");return signature.substr(0,argsIndex)}else{return signature}};var __embind_register_class_class_function=function(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,fn,isAsync,isNonnullReturn){rawClassType>>>=0;methodName>>>=0;rawArgTypesAddr>>>=0;invokerSignature>>>=0;rawInvoker>>>=0;fn>>>=0;var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=readLatin1String(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}var proto=classType.registeredClass.constructor;if(undefined===proto[methodName]){unboundTypesHandler.argCount=argCount-1;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-1]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));var func=craftInvokerFunction(humanName,invokerArgsArray,null,rawInvoker,fn,isAsync);if(undefined===proto[methodName].overloadTable){func.argCount=argCount-1;proto[methodName]=func}else{proto[methodName].overloadTable[argCount-1]=func}if(classType.registeredClass.__derivedClasses){for(const derivedClass of classType.registeredClass.__derivedClasses){if(!derivedClass.constructor.hasOwnProperty(methodName)){derivedClass.constructor[methodName]=func}}}return[]});return[]})};var __embind_register_class_constructor=function(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor){rawClassType>>>=0;rawArgTypesAddr>>>=0;invokerSignature>>>=0;invoker>>>=0;rawConstructor>>>=0;assert(argCount>0);var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var __embind_register_class_function=function(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync,isNonnullReturn){rawClassType>>>=0;methodName>>>=0;rawArgTypesAddr>>>=0;invokerSignature>>>=0;rawInvoker>>>=0;context>>>=0;var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=readLatin1String(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};var validateThis=(this_,classType,humanName)=>{if(!(this_ instanceof Object)){throwBindingError(`${humanName} with invalid "this": ${this_}`)}if(!(this_ instanceof classType.registeredClass.constructor)){throwBindingError(`${humanName} incompatible with "this" of type ${this_.constructor.name}`)}if(!this_.$$.ptr){throwBindingError(`cannot call emscripten binding method ${humanName} on deleted object`)}return upcastPointer(this_.$$.ptr,this_.$$.ptrType.registeredClass,classType.registeredClass)};var __embind_register_class_property=function(classType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext){classType>>>=0;fieldName>>>=0;getterReturnType>>>=0;getterSignature>>>=0;getter>>>=0;getterContext>>>=0;setterArgumentType>>>=0;setterSignature>>>=0;setter>>>=0;setterContext>>>=0;fieldName=readLatin1String(fieldName);getter=embind__requireFunction(getterSignature,getter);whenDependentTypesAreResolved([],[classType],classType=>{classType=classType[0];var humanName=`${classType.name}.${fieldName}`;var desc={get(){throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])},enumerable:true,configurable:true};if(setter){desc.set=()=>throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])}else{desc.set=v=>throwBindingError(humanName+" is a read-only property")}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);whenDependentTypesAreResolved([],setter?[getterReturnType,setterArgumentType]:[getterReturnType],types=>{var getterReturnType=types[0];var desc={get(){var ptr=validateThis(this,classType,humanName+" getter");return getterReturnType["fromWireType"](getter(getterContext,ptr))},enumerable:true};if(setter){setter=embind__requireFunction(setterSignature,setter);var setterArgumentType=types[1];desc.set=function(v){var ptr=validateThis(this,classType,humanName+" setter");var destructors=[];setter(setterContext,ptr,setterArgumentType["toWireType"](destructors,v));runDestructors(destructors)}}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);return[]});return[]})};function __emval_decref(handle){handle>>>=0;if(handle>9&&0===--emval_handles[handle+1]){assert(emval_handles[handle]!==undefined,`Decref for unallocated handle.`);emval_handles[handle]=undefined;emval_freelist.push(handle)}}var EmValType={name:"emscripten::val",fromWireType:handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},toWireType:(destructors,value)=>Emval.toHandle(value),argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,destructorFunction:null};function __embind_register_emval(rawType){rawType>>>=0;return registerType(rawType,EmValType)}var enumReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?function(pointer){return this["fromWireType"](GROWABLE_HEAP_I8()[pointer>>>0])}:function(pointer){return this["fromWireType"](GROWABLE_HEAP_U8()[pointer>>>0])};case 2:return signed?function(pointer){return this["fromWireType"](GROWABLE_HEAP_I16()[pointer>>>1>>>0])}:function(pointer){return this["fromWireType"](GROWABLE_HEAP_U16()[pointer>>>1>>>0])};case 4:return signed?function(pointer){return this["fromWireType"](GROWABLE_HEAP_I32()[pointer>>>2>>>0])}:function(pointer){return this["fromWireType"](GROWABLE_HEAP_U32()[pointer>>>2>>>0])};default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};function __embind_register_enum(rawType,name,size,isSigned){rawType>>>=0;name>>>=0;size>>>=0;name=readLatin1String(name);function ctor(){}ctor.values={};registerType(rawType,{name,constructor:ctor,fromWireType:function(c){return this.constructor.values[c]},toWireType:(destructors,c)=>c.value,argPackAdvance:GenericWireTypeSize,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor)}function __embind_register_enum_value(rawEnumType,name,enumValue){rawEnumType>>>=0;name>>>=0;var enumType=requireRegisteredType(rawEnumType,"enum");name=readLatin1String(name);var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(`${enumType.name}_${name}`,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value}var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this["fromWireType"](GROWABLE_HEAP_F32()[pointer>>>2>>>0])};case 8:return function(pointer){return this["fromWireType"](GROWABLE_HEAP_F64()[pointer>>>3>>>0])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=function(rawType,name,size){rawType>>>=0;name>>>=0;size>>>=0;name=readLatin1String(name);registerType(rawType,{name,fromWireType:value=>value,toWireType:(destructors,value)=>{if(typeof value!="number"&&typeof value!="boolean"){throw new TypeError(`Cannot convert ${embindRepr(value)} to ${this.name}`)}return value},argPackAdvance:GenericWireTypeSize,readValueFromPointer:floatReadValueFromPointer(name,size),destructorFunction:null})};function __embind_register_function(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync,isNonnullReturn){name>>>=0;rawArgTypesAddr>>>=0;signature>>>=0;rawInvoker>>>=0;fn>>>=0;var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);name=getFunctionName(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){primitiveType>>>=0;name>>>=0;size>>>=0;name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var fromWireType=value=>value;if(minRange===0){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift}var isUnsignedType=name.includes("unsigned");var checkAssertions=(value,toTypeName)=>{if(typeof value!="number"&&typeof value!="boolean"){throw new TypeError(`Cannot convert "${embindRepr(value)}" to ${toTypeName}`)}if(valuemaxRange){throw new TypeError(`Passing a number "${embindRepr(value)}" from JS side to C/C++ side to an argument of type "${name}", which is outside the valid range [${minRange}, ${maxRange}]!`)}};var toWireType;if(isUnsignedType){toWireType=function(destructors,value){checkAssertions(value,this.name);return value>>>0}}else{toWireType=function(destructors,value){checkAssertions(value,this.name);return value}}registerType(primitiveType,{name,fromWireType,toWireType,argPackAdvance:GenericWireTypeSize,readValueFromPointer:integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){rawType>>>=0;name>>>=0;var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=GROWABLE_HEAP_U32()[handle>>>2>>>0];var data=GROWABLE_HEAP_U32()[handle+4>>>2>>>0];return new TA(GROWABLE_HEAP_I8().buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name,fromWireType:decodeMemoryView,argPackAdvance:GenericWireTypeSize,readValueFromPointer:decodeMemoryView},{ignoreDuplicateRegistrations:true})}var __embind_register_smart_ptr=function(rawType,rawPointeeType,name,sharingPolicy,getPointeeSignature,rawGetPointee,constructorSignature,rawConstructor,shareSignature,rawShare,destructorSignature,rawDestructor){rawType>>>=0;rawPointeeType>>>=0;name>>>=0;getPointeeSignature>>>=0;rawGetPointee>>>=0;constructorSignature>>>=0;rawConstructor>>>=0;shareSignature>>>=0;rawShare>>>=0;destructorSignature>>>=0;rawDestructor>>>=0;name=readLatin1String(name);rawGetPointee=embind__requireFunction(getPointeeSignature,rawGetPointee);rawConstructor=embind__requireFunction(constructorSignature,rawConstructor);rawShare=embind__requireFunction(shareSignature,rawShare);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);whenDependentTypesAreResolved([rawType],[rawPointeeType],pointeeType=>{pointeeType=pointeeType[0];var registeredPointer=new RegisteredPointer(name,pointeeType.registeredClass,false,false,true,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor);return[registeredPointer]})};function __embind_register_std_string(rawType,name){rawType>>>=0;name>>>=0;name=readLatin1String(name);var stdStringIsUTF8=true;registerType(rawType,{name,fromWireType(value){var length=GROWABLE_HEAP_U32()[value>>>2>>>0];var payload=value+4;var str;if(stdStringIsUTF8){var decodeStartPtr=payload;for(var i=0;i<=length;++i){var currentBytePtr=payload+i;if(i==length||GROWABLE_HEAP_U8()[currentBytePtr>>>0]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>>0])}str=a.join("")}_free(value);return str},toWireType(destructors,value){if(value instanceof ArrayBuffer){value=new Uint8Array(value)}var length;var valueIsOfTypeString=typeof value=="string";if(!(valueIsOfTypeString||value instanceof Uint8Array||value instanceof Uint8ClampedArray||value instanceof Int8Array)){throwBindingError("Cannot pass non-string to std::string")}if(stdStringIsUTF8&&valueIsOfTypeString){length=lengthBytesUTF8(value)}else{length=value.length}var base=_malloc(4+length+1);var ptr=base+4;GROWABLE_HEAP_U32()[base>>>2>>>0]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}GROWABLE_HEAP_U8()[ptr+i>>>0]=charCode}}else{for(var i=0;i>>0]=value[i]}}}if(destructors!==null){destructors.push(_free,base)}return base},argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})}var UTF16Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf-16le"):undefined;var UTF16ToString=(ptr,maxBytesToRead)=>{assert(ptr%2==0,"Pointer passed to UTF16ToString must be aligned to two bytes!");var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&GROWABLE_HEAP_U16()[idx>>>0])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder)return UTF16Decoder.decode(GROWABLE_HEAP_U8().slice(ptr,endPtr));var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=GROWABLE_HEAP_I16()[ptr+i*2>>>1>>>0];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str};var stringToUTF16=(str,outPtr,maxBytesToWrite)=>{assert(outPtr%2==0,"Pointer passed to stringToUTF16 must be aligned to two bytes!");assert(typeof maxBytesToWrite=="number","stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>>1>>>0]=codeUnit;outPtr+=2}GROWABLE_HEAP_I16()[outPtr>>>1>>>0]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead)=>{assert(ptr%4==0,"Pointer passed to UTF32ToString must be aligned to four bytes!");var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=GROWABLE_HEAP_I32()[ptr+i*4>>>2>>>0];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{outPtr>>>=0;assert(outPtr%4==0,"Pointer passed to stringToUTF32 must be aligned to four bytes!");assert(typeof maxBytesToWrite=="number","stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}GROWABLE_HEAP_I32()[outPtr>>>2>>>0]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}GROWABLE_HEAP_I32()[outPtr>>>2>>>0]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len};var __embind_register_std_wstring=function(rawType,charSize,name){rawType>>>=0;charSize>>>=0;name>>>=0;name=readLatin1String(name);var decodeString,encodeString,readCharAt,lengthBytesUTF;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16;readCharAt=pointer=>GROWABLE_HEAP_U16()[pointer>>>1>>>0]}else if(charSize===4){decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32;readCharAt=pointer=>GROWABLE_HEAP_U32()[pointer>>>2>>>0]}registerType(rawType,{name,fromWireType:value=>{var length=GROWABLE_HEAP_U32()[value>>>2>>>0];var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||readCharAt(currentBytePtr)==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},toWireType:(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);GROWABLE_HEAP_U32()[ptr>>>2>>>0]=length/charSize;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};function __embind_register_value_object(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor){rawType>>>=0;name>>>=0;constructorSignature>>>=0;rawConstructor>>>=0;destructorSignature>>>=0;rawDestructor>>>=0;structRegistrations[rawType]={name:readLatin1String(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}}function __embind_register_value_object_field(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext){structType>>>=0;fieldName>>>=0;getterReturnType>>>=0;getterSignature>>>=0;getter>>>=0;getterContext>>>=0;setterArgumentType>>>=0;setterSignature>>>=0;setter>>>=0;setterContext>>>=0;structRegistrations[structType].fields.push({fieldName:readLatin1String(fieldName),getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext,setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext})}var __embind_register_void=function(rawType,name){rawType>>>=0;name>>>=0;name=readLatin1String(name);registerType(rawType,{isVoid:true,name,argPackAdvance:0,fromWireType:()=>undefined,toWireType:(destructors,o)=>undefined})};function __emscripten_init_main_thread_js(tb){tb>>>=0;__emscripten_thread_init(tb,!ENVIRONMENT_IS_WORKER,1,!ENVIRONMENT_IS_WEB,2097152,false);PThread.threadInitTLS()}var maybeExit=()=>{if(!keepRuntimeAlive()){try{if(ENVIRONMENT_IS_PTHREAD)__emscripten_thread_exit(EXITSTATUS);else _exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){err("user callback triggered after runtime exited or application aborted. Ignoring.");return}try{func();maybeExit()}catch(e){handleException(e)}};function __emscripten_thread_mailbox_await(pthread_ptr){pthread_ptr>>>=0;if(typeof Atomics.waitAsync==="function"){var wait=Atomics.waitAsync(GROWABLE_HEAP_I32(),pthread_ptr>>>2,pthread_ptr);assert(wait.async);wait.value.then(checkMailbox);var waitingAsync=pthread_ptr+128;Atomics.store(GROWABLE_HEAP_I32(),waitingAsync>>>2,1)}}var checkMailbox=()=>{var pthread_ptr=_pthread_self();if(pthread_ptr){__emscripten_thread_mailbox_await(pthread_ptr);callUserCallback(__emscripten_check_mailbox)}};function __emscripten_notify_mailbox_postmessage(targetThread,currThreadId){targetThread>>>=0;currThreadId>>>=0;if(targetThread==currThreadId){setTimeout(checkMailbox)}else if(ENVIRONMENT_IS_PTHREAD){postMessage({targetThread,cmd:"checkMailbox"})}else{var worker=PThread.pthreads[targetThread];if(!worker){err(`Cannot send message to thread with ID ${targetThread}, unknown thread ID!`);return}worker.postMessage({cmd:"checkMailbox"})}}var proxiedJSCallArgs=[];function __emscripten_receive_on_main_thread_js(funcIndex,emAsmAddr,callingThread,numCallArgs,args){emAsmAddr>>>=0;callingThread>>>=0;args>>>=0;numCallArgs/=2;proxiedJSCallArgs.length=numCallArgs;var b=args>>>3;for(var i=0;i>>0]}}var func=emAsmAddr?ASM_CONSTS[emAsmAddr]:proxiedFunctionTable[funcIndex];assert(!(funcIndex&&emAsmAddr));assert(func.length==numCallArgs,"Call args mismatch in _emscripten_receive_on_main_thread_js");PThread.currentProxiedOperationCallerThread=callingThread;var rtn=func(...proxiedJSCallArgs);PThread.currentProxiedOperationCallerThread=0;assert(typeof rtn!="bigint");return rtn}var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};function __emscripten_thread_cleanup(thread){thread>>>=0;if(!ENVIRONMENT_IS_PTHREAD)cleanupThread(thread);else postMessage({cmd:"cleanupThread",thread})}function __emscripten_thread_set_strongref(thread){thread>>>=0;if(ENVIRONMENT_IS_NODE){PThread.pthreads[thread].ref()}}var emval_returnValue=(returnType,destructorsRef,handle)=>{var destructors=[];var result=returnType["toWireType"](destructors,handle);if(destructors.length){GROWABLE_HEAP_U32()[destructorsRef>>>2>>>0]=Emval.toHandle(destructors)}return result};function __emval_as(handle,returnType,destructorsRef){handle>>>=0;returnType>>>=0;destructorsRef>>>=0;handle=Emval.toValue(handle);returnType=requireRegisteredType(returnType,"emval::as");return emval_returnValue(returnType,destructorsRef,handle)}function __emval_as_int64(handle,returnType){handle>>>=0;returnType>>>=0;handle=Emval.toValue(handle);returnType=requireRegisteredType(returnType,"emval::as");return returnType["toWireType"](null,handle)}function __emval_as_uint64(handle,returnType){handle>>>=0;returnType>>>=0;handle=Emval.toValue(handle);returnType=requireRegisteredType(returnType,"emval::as");return returnType["toWireType"](null,handle)}var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}return symbol};var emval_methodCallers=[];function __emval_call_method(caller,objHandle,methodName,destructorsRef,args){caller>>>=0;objHandle>>>=0;methodName>>>=0;destructorsRef>>>=0;args>>>=0;caller=emval_methodCallers[caller];objHandle=Emval.toValue(objHandle);methodName=getStringOrSymbol(methodName);return caller(objHandle,objHandle[methodName],destructorsRef,args)}var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i>>2>>>0],"parameter "+i)}return a};var reflectConstruct=Reflect.construct;function __emval_get_method_caller(argCount,argTypes,kind){argTypes>>>=0;var types=emval_lookupTypes(argCount,argTypes);var retType=types.shift();argCount--;var functionBody=`return function (obj, func, destructorsRef, args) {\n`;var offset=0;var argsList=[];if(kind===0){argsList.push("obj")}var params=["retType"];var args=[retType];for(var i=0;it.name).join(", ")}) => ${retType.name}>`;return emval_addMethodCaller(createNamedFunction(functionName,invokerFunction))}function __emval_get_property(handle,key){handle>>>=0;key>>>=0;handle=Emval.toValue(handle);key=Emval.toValue(key);return Emval.toHandle(handle[key])}function __emval_new_cstring(v){v>>>=0;return Emval.toHandle(getStringOrSymbol(v))}function __emval_run_destructors(handle){handle>>>=0;var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)}function __emval_take_value(type,arg){type>>>=0;arg>>>=0;type=requireRegisteredType(type,"_emval_take_value");var v=type["readValueFromPointer"](arg);return Emval.toHandle(v)}function __gmtime_js(time,tmPtr){time=bigintToI53Checked(time);tmPtr>>>=0;var date=new Date(time*1e3);GROWABLE_HEAP_I32()[tmPtr>>>2>>>0]=date.getUTCSeconds();GROWABLE_HEAP_I32()[tmPtr+4>>>2>>>0]=date.getUTCMinutes();GROWABLE_HEAP_I32()[tmPtr+8>>>2>>>0]=date.getUTCHours();GROWABLE_HEAP_I32()[tmPtr+12>>>2>>>0]=date.getUTCDate();GROWABLE_HEAP_I32()[tmPtr+16>>>2>>>0]=date.getUTCMonth();GROWABLE_HEAP_I32()[tmPtr+20>>>2>>>0]=date.getUTCFullYear()-1900;GROWABLE_HEAP_I32()[tmPtr+24>>>2>>>0]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;GROWABLE_HEAP_I32()[tmPtr+28>>>2>>>0]=yday}var isLeapYear=year=>year%4===0&&(year%100!==0||year%400===0);var MONTH_DAYS_LEAP_CUMULATIVE=[0,31,60,91,121,152,182,213,244,274,305,335];var MONTH_DAYS_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];var ydayFromDate=date=>{var leap=isLeapYear(date.getFullYear());var monthDaysCumulative=leap?MONTH_DAYS_LEAP_CUMULATIVE:MONTH_DAYS_REGULAR_CUMULATIVE;var yday=monthDaysCumulative[date.getMonth()]+date.getDate()-1;return yday};function __localtime_js(time,tmPtr){time=bigintToI53Checked(time);tmPtr>>>=0;var date=new Date(time*1e3);GROWABLE_HEAP_I32()[tmPtr>>>2>>>0]=date.getSeconds();GROWABLE_HEAP_I32()[tmPtr+4>>>2>>>0]=date.getMinutes();GROWABLE_HEAP_I32()[tmPtr+8>>>2>>>0]=date.getHours();GROWABLE_HEAP_I32()[tmPtr+12>>>2>>>0]=date.getDate();GROWABLE_HEAP_I32()[tmPtr+16>>>2>>>0]=date.getMonth();GROWABLE_HEAP_I32()[tmPtr+20>>>2>>>0]=date.getFullYear()-1900;GROWABLE_HEAP_I32()[tmPtr+24>>>2>>>0]=date.getDay();var yday=ydayFromDate(date)|0;GROWABLE_HEAP_I32()[tmPtr+28>>>2>>>0]=yday;GROWABLE_HEAP_I32()[tmPtr+36>>>2>>>0]=-(date.getTimezoneOffset()*60);var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;GROWABLE_HEAP_I32()[tmPtr+32>>>2>>>0]=dst}var __mktime_js=function(tmPtr){tmPtr>>>=0;var ret=(()=>{var date=new Date(GROWABLE_HEAP_I32()[tmPtr+20>>>2>>>0]+1900,GROWABLE_HEAP_I32()[tmPtr+16>>>2>>>0],GROWABLE_HEAP_I32()[tmPtr+12>>>2>>>0],GROWABLE_HEAP_I32()[tmPtr+8>>>2>>>0],GROWABLE_HEAP_I32()[tmPtr+4>>>2>>>0],GROWABLE_HEAP_I32()[tmPtr>>>2>>>0],0);var dst=GROWABLE_HEAP_I32()[tmPtr+32>>>2>>>0];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){GROWABLE_HEAP_I32()[tmPtr+32>>>2>>>0]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}GROWABLE_HEAP_I32()[tmPtr+24>>>2>>>0]=date.getDay();var yday=ydayFromDate(date)|0;GROWABLE_HEAP_I32()[tmPtr+28>>>2>>>0]=yday;GROWABLE_HEAP_I32()[tmPtr>>>2>>>0]=date.getSeconds();GROWABLE_HEAP_I32()[tmPtr+4>>>2>>>0]=date.getMinutes();GROWABLE_HEAP_I32()[tmPtr+8>>>2>>>0]=date.getHours();GROWABLE_HEAP_I32()[tmPtr+12>>>2>>>0]=date.getDate();GROWABLE_HEAP_I32()[tmPtr+16>>>2>>>0]=date.getMonth();GROWABLE_HEAP_I32()[tmPtr+20>>>2>>>0]=date.getYear();var timeMs=date.getTime();if(isNaN(timeMs)){return-1}return timeMs/1e3})();return BigInt(ret)};function __mmap_js(len,prot,flags,fd,offset,allocated,addr){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(39,0,1,len,prot,flags,fd,offset,allocated,addr);len>>>=0;offset=bigintToI53Checked(offset);allocated>>>=0;addr>>>=0;try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;GROWABLE_HEAP_I32()[allocated>>>2>>>0]=res.allocated;GROWABLE_HEAP_U32()[addr>>>2>>>0]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(40,0,1,addr,len,prot,flags,fd,offset);addr>>>=0;len>>>=0;offset=bigintToI53Checked(offset);try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __timegm_js=function(tmPtr){tmPtr>>>=0;var ret=(()=>{var time=Date.UTC(GROWABLE_HEAP_I32()[tmPtr+20>>>2>>>0]+1900,GROWABLE_HEAP_I32()[tmPtr+16>>>2>>>0],GROWABLE_HEAP_I32()[tmPtr+12>>>2>>>0],GROWABLE_HEAP_I32()[tmPtr+8>>>2>>>0],GROWABLE_HEAP_I32()[tmPtr+4>>>2>>>0],GROWABLE_HEAP_I32()[tmPtr>>>2>>>0],0);var date=new Date(time);GROWABLE_HEAP_I32()[tmPtr+24>>>2>>>0]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;GROWABLE_HEAP_I32()[tmPtr+28>>>2>>>0]=yday;return date.getTime()/1e3})();return BigInt(ret)};var __tzset_js=function(timezone,daylight,std_name,dst_name){timezone>>>=0;daylight>>>=0;std_name>>>=0;dst_name>>>=0;var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);GROWABLE_HEAP_U32()[timezone>>>2>>>0]=stdTimezoneOffset*60;GROWABLE_HEAP_I32()[daylight>>>2>>>0]=Number(winterOffset!=summerOffset);var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);assert(winterName);assert(summerName);assert(lengthBytesUTF8(winterName)<=16,`timezone name truncated to fit in TZNAME_MAX (${winterName})`);assert(lengthBytesUTF8(summerName)<=16,`timezone name truncated to fit in TZNAME_MAX (${summerName})`);if(summerOffsetperformance.timeOrigin+performance.now();var _emscripten_date_now=()=>Date.now();var nowIsMonotonic=1;var checkWasiClock=clock_id=>clock_id>=0&&clock_id<=3;function _clock_time_get(clk_id,ignored_precision,ptime){ignored_precision=bigintToI53Checked(ignored_precision);ptime>>>=0;if(!checkWasiClock(clk_id)){return 28}var now;if(clk_id===0){now=_emscripten_date_now()}else if(nowIsMonotonic){now=_emscripten_get_now()}else{return 52}var nsec=Math.round(now*1e3*1e3);HEAP64[ptime>>>3]=BigInt(nsec);return 0}var readEmAsmArgsArray=[];var readEmAsmArgs=(sigPtr,buf)=>{assert(Array.isArray(readEmAsmArgsArray));assert(buf%16==0);readEmAsmArgsArray.length=0;var ch;while(ch=GROWABLE_HEAP_U8()[sigPtr++>>>0]){var chr=String.fromCharCode(ch);var validChars=["d","f","i","p"];validChars.push("j");assert(validChars.includes(chr),`Invalid character ${ch}("${chr}") in readEmAsmArgs! Use only [${validChars}], and do not specify "v" for void return argument.`);var wide=ch!=105;wide&=ch!=112;buf+=wide&&buf%8?4:0;readEmAsmArgsArray.push(ch==112?GROWABLE_HEAP_U32()[buf>>>2>>>0]:ch==106?HEAP64[buf>>>3]:ch==105?GROWABLE_HEAP_I32()[buf>>>2>>>0]:GROWABLE_HEAP_F64()[buf>>>3>>>0]);buf+=wide?8:4}return readEmAsmArgsArray};var runEmAsmFunction=(code,sigPtr,argbuf)=>{var args=readEmAsmArgs(sigPtr,argbuf);assert(ASM_CONSTS.hasOwnProperty(code),`No EM_ASM constant found at address ${code}. The loaded WebAssembly file is likely out of sync with the generated JavaScript.`);return ASM_CONSTS[code](...args)};function _emscripten_asm_const_int(code,sigPtr,argbuf){code>>>=0;sigPtr>>>=0;argbuf>>>=0;return runEmAsmFunction(code,sigPtr,argbuf)}var _emscripten_check_blocking_allowed=()=>{if(ENVIRONMENT_IS_NODE)return;if(ENVIRONMENT_IS_WORKER)return;warnOnce("Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread")};function _emscripten_err(str){str>>>=0;return err(UTF8ToString(str))}var _emscripten_exit_with_live_runtime=()=>{runtimeKeepalivePush();throw"unwind"};var getHeapMax=()=>4294901760;function _emscripten_get_heap_max(){return getHeapMax()}var _emscripten_num_logical_cores=()=>ENVIRONMENT_IS_NODE?require("os").cpus().length:navigator["hardwareConcurrency"];var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){err(`growMemory: Attempted to grow heap from ${b.byteLength} bytes to ${size} bytes, but got error: ${e}`)}};function _emscripten_resize_heap(requestedSize){requestedSize>>>=0;var oldSize=GROWABLE_HEAP_U8().length;if(requestedSize<=oldSize){return false}var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`);return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`);return false}var _emscripten_runtime_keepalive_check=keepRuntimeAlive;var _emscripten_unwind_to_js_event_loop=()=>{throw"unwind"};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var stringToAscii=(str,buffer)=>{for(var i=0;i>>0]=str.charCodeAt(i)}GROWABLE_HEAP_I8()[buffer>>>0]=0};var _environ_get=function(__environ,environ_buf){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(41,0,1,__environ,environ_buf);__environ>>>=0;environ_buf>>>=0;var bufSize=0;getEnvStrings().forEach((string,i)=>{var ptr=environ_buf+bufSize;GROWABLE_HEAP_U32()[__environ+i*4>>>2>>>0]=ptr;stringToAscii(string,ptr);bufSize+=string.length+1});return 0};var _environ_sizes_get=function(penviron_count,penviron_buf_size){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(42,0,1,penviron_count,penviron_buf_size);penviron_count>>>=0;penviron_buf_size>>>=0;var strings=getEnvStrings();GROWABLE_HEAP_U32()[penviron_count>>>2>>>0]=strings.length;var bufSize=0;strings.forEach(string=>bufSize+=string.length+1);GROWABLE_HEAP_U32()[penviron_buf_size>>>2>>>0]=bufSize;return 0};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(43,0,1,fd);try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(44,0,1,fd,pbuf);pbuf>>>=0;try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}GROWABLE_HEAP_I8()[pbuf>>>0]=type;GROWABLE_HEAP_I16()[pbuf+2>>>1>>>0]=flags;HEAP64[pbuf+8>>>3]=BigInt(rightsBase);HEAP64[pbuf+16>>>3]=BigInt(rightsInheriting);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>>2>>>0];var len=GROWABLE_HEAP_U32()[iov+4>>>2>>>0];iov+=8;var curr=FS.read(stream,GROWABLE_HEAP_I8(),ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>>=0;iovcnt>>>=0;offset=bigintToI53Checked(offset);pnum>>>=0;try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);var num=doReadv(stream,iov,iovcnt,offset);GROWABLE_HEAP_U32()[pnum>>>2>>>0]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>>2>>>0];var len=GROWABLE_HEAP_U32()[iov+4>>>2>>>0];iov+=8;var curr=FS.write(stream,GROWABLE_HEAP_I8(),ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>>=0;iovcnt>>>=0;offset=bigintToI53Checked(offset);pnum>>>=0;try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt,offset);GROWABLE_HEAP_U32()[pnum>>>2>>>0]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_read(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(47,0,1,fd,iov,iovcnt,pnum);iov>>>=0;iovcnt>>>=0;pnum>>>=0;try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doReadv(stream,iov,iovcnt);GROWABLE_HEAP_U32()[pnum>>>2>>>0]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(48,0,1,fd,offset,whence,newOffset);offset=bigintToI53Checked(offset);newOffset>>>=0;try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);HEAP64[newOffset>>>3]=BigInt(stream.position);if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_sync(fd){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(49,0,1,fd);try{var stream=SYSCALLS.getStreamFromFD(fd);if(stream.stream_ops?.fsync){return stream.stream_ops.fsync(stream)}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(50,0,1,fd,iov,iovcnt,pnum);iov>>>=0;iovcnt>>>=0;pnum>>>=0;try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);GROWABLE_HEAP_U32()[pnum>>>2>>>0]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _getaddrinfo(node,service,hint,out){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(51,0,1,node,service,hint,out);node>>>=0;service>>>=0;hint>>>=0;out>>>=0;var addr=0;var port=0;var flags=0;var family=0;var type=0;var proto=0;var ai;function allocaddrinfo(family,type,proto,canon,addr,port){var sa,salen,ai;var errno;salen=family===10?28:16;addr=family===10?inetNtop6(addr):inetNtop4(addr);sa=_malloc(salen);errno=writeSockaddr(sa,family,addr,port);assert(!errno);ai=_malloc(32);GROWABLE_HEAP_I32()[ai+4>>>2>>>0]=family;GROWABLE_HEAP_I32()[ai+8>>>2>>>0]=type;GROWABLE_HEAP_I32()[ai+12>>>2>>>0]=proto;GROWABLE_HEAP_U32()[ai+24>>>2>>>0]=canon;GROWABLE_HEAP_U32()[ai+20>>>2>>>0]=sa;if(family===10){GROWABLE_HEAP_I32()[ai+16>>>2>>>0]=28}else{GROWABLE_HEAP_I32()[ai+16>>>2>>>0]=16}GROWABLE_HEAP_I32()[ai+28>>>2>>>0]=0;return ai}if(hint){flags=GROWABLE_HEAP_I32()[hint>>>2>>>0];family=GROWABLE_HEAP_I32()[hint+4>>>2>>>0];type=GROWABLE_HEAP_I32()[hint+8>>>2>>>0];proto=GROWABLE_HEAP_I32()[hint+12>>>2>>>0]}if(type&&!proto){proto=type===2?17:6}if(!type&&proto){type=proto===17?2:1}if(proto===0){proto=6}if(type===0){type=1}if(!node&&!service){return-2}if(flags&~(1|2|4|1024|8|16|32)){return-1}if(hint!==0&&GROWABLE_HEAP_I32()[hint>>>2>>>0]&2&&!node){return-1}if(flags&32){return-2}if(type!==0&&type!==1&&type!==2){return-7}if(family!==0&&family!==2&&family!==10){return-6}if(service){service=UTF8ToString(service);port=parseInt(service,10);if(isNaN(port)){if(flags&1024){return-2}return-8}}if(!node){if(family===0){family=2}if((flags&1)===0){if(family===2){addr=_htonl(2130706433)}else{addr=[0,0,0,_htonl(1)]}}ai=allocaddrinfo(family,type,proto,null,addr,port);GROWABLE_HEAP_U32()[out>>>2>>>0]=ai;return 0}node=UTF8ToString(node);addr=inetPton4(node);if(addr!==null){if(family===0||family===2){family=2}else if(family===10&&flags&8){addr=[0,0,_htonl(65535),addr];family=10}else{return-2}}else{addr=inetPton6(node);if(addr!==null){if(family===0||family===10){family=10}else{return-2}}}if(addr!=null){ai=allocaddrinfo(family,type,proto,node,addr,port);GROWABLE_HEAP_U32()[out>>>2>>>0]=ai;return 0}if(flags&4){return-2}node=DNS.lookup_name(node);addr=inetPton4(node);if(family===0){family=2}else if(family===10){addr=[0,0,_htonl(65535),addr]}ai=allocaddrinfo(family,type,proto,null,addr,port);GROWABLE_HEAP_U32()[out>>>2>>>0]=ai;return 0}function _getnameinfo(sa,salen,node,nodelen,serv,servlen,flags){sa>>>=0;node>>>=0;serv>>>=0;var info=readSockaddr(sa,salen);if(info.errno){return-6}var port=info.port;var addr=info.addr;var overflowed=false;if(node&&nodelen){var lookup;if(flags&1||!(lookup=DNS.lookup_addr(addr))){if(flags&8){return-2}}else{addr=lookup}var numBytesWrittenExclNull=stringToUTF8(addr,node,nodelen);if(numBytesWrittenExclNull+1>=nodelen){overflowed=true}}if(serv&&servlen){port=""+port;var numBytesWrittenExclNull=stringToUTF8(port,serv,servlen);if(numBytesWrittenExclNull+1>=servlen){overflowed=true}}if(overflowed){return-12}return 0}function _random_get(buffer,size){buffer>>>=0;size>>>=0;try{randomFill(GROWABLE_HEAP_U8().subarray(buffer>>>0,buffer+size>>>0));return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var getCFunc=ident=>{var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func};var writeArrayToMemory=(array,buffer)=>{assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");GROWABLE_HEAP_I8().set(array,buffer>>>0)};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i(...args)=>ccall(ident,returnType,argTypes,args,opts);var FS_createPath=FS.createPath;var FS_unlink=path=>FS.unlink(path);var FS_createLazyFile=FS.createLazyFile;var FS_createDevice=FS.createDevice;var incrementExceptionRefcount=ex=>{var ptr=getCppExceptionThrownObjectFromWebAssemblyException(ex);___cxa_increment_exception_refcount(ptr)};Module["incrementExceptionRefcount"]=incrementExceptionRefcount;var decrementExceptionRefcount=ex=>{var ptr=getCppExceptionThrownObjectFromWebAssemblyException(ex);___cxa_decrement_exception_refcount(ptr)};Module["decrementExceptionRefcount"]=decrementExceptionRefcount;PThread.init();FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_unlink"]=FS.unlink;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;BindingError=Module["BindingError"]=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};init_emval();PureVirtualError=Module["PureVirtualError"]=extendError(Error,"PureVirtualError");embind_init_charCodes();InternalError=Module["InternalError"]=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};init_ClassHandle();init_RegisteredPointer();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");var proxiedFunctionTable=[_proc_exit,exitOnMainThread,pthreadCreateProxied,___syscall_accept4,___syscall_bind,___syscall_chdir,___syscall_chmod,___syscall_connect,___syscall_dup,___syscall_dup3,___syscall_faccessat,___syscall_fchmodat2,___syscall_fchownat,___syscall_fcntl64,___syscall_fstat64,___syscall_ftruncate64,___syscall_getcwd,___syscall_getdents64,___syscall_getpeername,___syscall_getsockname,___syscall_getsockopt,___syscall_ioctl,___syscall_listen,___syscall_lstat64,___syscall_mkdirat,___syscall_newfstatat,___syscall_openat,___syscall_pipe,___syscall_poll,___syscall_readlinkat,___syscall_recvfrom,___syscall_renameat,___syscall_rmdir,___syscall_sendto,___syscall_socket,___syscall_stat64,___syscall_symlinkat,___syscall_unlinkat,___syscall_utimensat,__mmap_js,__munmap_js,_environ_get,_environ_sizes_get,_fd_close,_fd_fdstat_get,_fd_pread,_fd_pwrite,_fd_read,_fd_seek,_fd_sync,_fd_write,_getaddrinfo];function checkIncomingModuleAPI(){ignoredModuleProp("fetchSettings")}var wasmImports;function assignWasmImports(){wasmImports={__assert_fail:___assert_fail,__call_sighandler:___call_sighandler,__pthread_create_js:___pthread_create_js,__syscall_accept4:___syscall_accept4,__syscall_bind:___syscall_bind,__syscall_chdir:___syscall_chdir,__syscall_chmod:___syscall_chmod,__syscall_connect:___syscall_connect,__syscall_dup:___syscall_dup,__syscall_dup3:___syscall_dup3,__syscall_faccessat:___syscall_faccessat,__syscall_fchmodat2:___syscall_fchmodat2,__syscall_fchownat:___syscall_fchownat,__syscall_fcntl64:___syscall_fcntl64,__syscall_fstat64:___syscall_fstat64,__syscall_ftruncate64:___syscall_ftruncate64,__syscall_getcwd:___syscall_getcwd,__syscall_getdents64:___syscall_getdents64,__syscall_getpeername:___syscall_getpeername,__syscall_getsockname:___syscall_getsockname,__syscall_getsockopt:___syscall_getsockopt,__syscall_ioctl:___syscall_ioctl,__syscall_listen:___syscall_listen,__syscall_lstat64:___syscall_lstat64,__syscall_mkdirat:___syscall_mkdirat,__syscall_newfstatat:___syscall_newfstatat,__syscall_openat:___syscall_openat,__syscall_pipe:___syscall_pipe,__syscall_poll:___syscall_poll,__syscall_readlinkat:___syscall_readlinkat,__syscall_recvfrom:___syscall_recvfrom,__syscall_renameat:___syscall_renameat,__syscall_rmdir:___syscall_rmdir,__syscall_sendto:___syscall_sendto,__syscall_socket:___syscall_socket,__syscall_stat64:___syscall_stat64,__syscall_symlinkat:___syscall_symlinkat,__syscall_unlinkat:___syscall_unlinkat,__syscall_utimensat:___syscall_utimensat,__throw_exception_with_stack_trace:___throw_exception_with_stack_trace,_abort_js:__abort_js,_embind_create_inheriting_constructor:__embind_create_inheriting_constructor,_embind_finalize_value_object:__embind_finalize_value_object,_embind_register_bigint:__embind_register_bigint,_embind_register_bool:__embind_register_bool,_embind_register_class:__embind_register_class,_embind_register_class_class_function:__embind_register_class_class_function,_embind_register_class_constructor:__embind_register_class_constructor,_embind_register_class_function:__embind_register_class_function,_embind_register_class_property:__embind_register_class_property,_embind_register_emval:__embind_register_emval,_embind_register_enum:__embind_register_enum,_embind_register_enum_value:__embind_register_enum_value,_embind_register_float:__embind_register_float,_embind_register_function:__embind_register_function,_embind_register_integer:__embind_register_integer,_embind_register_memory_view:__embind_register_memory_view,_embind_register_smart_ptr:__embind_register_smart_ptr,_embind_register_std_string:__embind_register_std_string,_embind_register_std_wstring:__embind_register_std_wstring,_embind_register_value_object:__embind_register_value_object,_embind_register_value_object_field:__embind_register_value_object_field,_embind_register_void:__embind_register_void,_emscripten_init_main_thread_js:__emscripten_init_main_thread_js,_emscripten_notify_mailbox_postmessage:__emscripten_notify_mailbox_postmessage,_emscripten_receive_on_main_thread_js:__emscripten_receive_on_main_thread_js,_emscripten_runtime_keepalive_clear:__emscripten_runtime_keepalive_clear,_emscripten_thread_cleanup:__emscripten_thread_cleanup,_emscripten_thread_mailbox_await:__emscripten_thread_mailbox_await,_emscripten_thread_set_strongref:__emscripten_thread_set_strongref,_emval_as:__emval_as,_emval_as_int64:__emval_as_int64,_emval_as_uint64:__emval_as_uint64,_emval_call_method:__emval_call_method,_emval_decref:__emval_decref,_emval_get_method_caller:__emval_get_method_caller,_emval_get_property:__emval_get_property,_emval_new_cstring:__emval_new_cstring,_emval_run_destructors:__emval_run_destructors,_emval_take_value:__emval_take_value,_gmtime_js:__gmtime_js,_localtime_js:__localtime_js,_mktime_js:__mktime_js,_mmap_js:__mmap_js,_munmap_js:__munmap_js,_timegm_js:__timegm_js,_tzset_js:__tzset_js,clock_time_get:_clock_time_get,emscripten_asm_const_int:_emscripten_asm_const_int,emscripten_check_blocking_allowed:_emscripten_check_blocking_allowed,emscripten_date_now:_emscripten_date_now,emscripten_err:_emscripten_err,emscripten_exit_with_live_runtime:_emscripten_exit_with_live_runtime,emscripten_get_heap_max:_emscripten_get_heap_max,emscripten_get_now:_emscripten_get_now,emscripten_num_logical_cores:_emscripten_num_logical_cores,emscripten_resize_heap:_emscripten_resize_heap,emscripten_runtime_keepalive_check:_emscripten_runtime_keepalive_check,emscripten_unwind_to_js_event_loop:_emscripten_unwind_to_js_event_loop,environ_get:_environ_get,environ_sizes_get:_environ_sizes_get,exit:_exit,fd_close:_fd_close,fd_fdstat_get:_fd_fdstat_get,fd_pread:_fd_pread,fd_pwrite:_fd_pwrite,fd_read:_fd_read,fd_seek:_fd_seek,fd_sync:_fd_sync,fd_write:_fd_write,getaddrinfo:_getaddrinfo,getnameinfo:_getnameinfo,jsRegisterChar,jsRegisterString,memory:wasmMemory,proc_exit:_proc_exit,random_get:_random_get}}var wasmExports;createWasm();var ___wasm_call_ctors=createExportWrapper("__wasm_call_ctors",0);var ___getTypeName=createExportWrapper("__getTypeName",1);var __embind_initialize_bindings=createExportWrapper("_embind_initialize_bindings",0);var _malloc=Module["_malloc"]=createExportWrapper("malloc",1);var _pthread_self=()=>(_pthread_self=wasmExports["pthread_self"])();var _main=Module["_main"]=createExportWrapper("__main_argc_argv",2);var _fflush=createExportWrapper("fflush",1);var _free=Module["_free"]=createExportWrapper("free",1);var _htonl=createExportWrapper("htonl",1);var _htons=createExportWrapper("htons",1);var _ntohs=createExportWrapper("ntohs",1);var _strerror=createExportWrapper("strerror",1);var _libreofficekit_hook_2=Module["_libreofficekit_hook_2"]=createExportWrapper("libreofficekit_hook_2",2);var _libreofficekit_hook=Module["_libreofficekit_hook"]=createExportWrapper("libreofficekit_hook",1);var _lok_preinit=Module["_lok_preinit"]=createExportWrapper("lok_preinit",2);var _lok_preinit_2=Module["_lok_preinit_2"]=createExportWrapper("lok_preinit_2",3);var _lok_documentLoad=Module["_lok_documentLoad"]=createExportWrapper("lok_documentLoad",2);var _lok_documentLoadWithOptions=Module["_lok_documentLoadWithOptions"]=createExportWrapper("lok_documentLoadWithOptions",3);var _lok_documentSaveAs=Module["_lok_documentSaveAs"]=createExportWrapper("lok_documentSaveAs",4);var _lok_documentDestroy=Module["_lok_documentDestroy"]=createExportWrapper("lok_documentDestroy",1);var _lok_getError=Module["_lok_getError"]=createExportWrapper("lok_getError",1);var _lok_destroy=Module["_lok_destroy"]=createExportWrapper("lok_destroy",1);var _lok_documentGetParts=Module["_lok_documentGetParts"]=createExportWrapper("lok_documentGetParts",1);var _lok_documentGetPart=Module["_lok_documentGetPart"]=createExportWrapper("lok_documentGetPart",1);var _lok_documentSetPart=Module["_lok_documentSetPart"]=createExportWrapper("lok_documentSetPart",2);var _lok_documentGetDocumentType=Module["_lok_documentGetDocumentType"]=createExportWrapper("lok_documentGetDocumentType",1);var _lok_documentGetDocumentSize=Module["_lok_documentGetDocumentSize"]=createExportWrapper("lok_documentGetDocumentSize",3);var _lok_documentInitializeForRendering=Module["_lok_documentInitializeForRendering"]=createExportWrapper("lok_documentInitializeForRendering",2);var _lok_documentPaintTile=Module["_lok_documentPaintTile"]=createExportWrapper("lok_documentPaintTile",8);var _lok_documentGetTileMode=Module["_lok_documentGetTileMode"]=createExportWrapper("lok_documentGetTileMode",1);var _lok_documentGetTextSelection=Module["_lok_documentGetTextSelection"]=createExportWrapper("lok_documentGetTextSelection",3);var _lok_documentSetTextSelection=Module["_lok_documentSetTextSelection"]=createExportWrapper("lok_documentSetTextSelection",4);var _lok_documentGetSelectionType=Module["_lok_documentGetSelectionType"]=createExportWrapper("lok_documentGetSelectionType",1);var _lok_documentResetSelection=Module["_lok_documentResetSelection"]=createExportWrapper("lok_documentResetSelection",1);var _lok_documentPostMouseEvent=Module["_lok_documentPostMouseEvent"]=createExportWrapper("lok_documentPostMouseEvent",7);var _lok_documentPostKeyEvent=Module["_lok_documentPostKeyEvent"]=createExportWrapper("lok_documentPostKeyEvent",4);var _lok_documentPostUnoCommand=Module["_lok_documentPostUnoCommand"]=createExportWrapper("lok_documentPostUnoCommand",4);var _lok_documentGetCommandValues=Module["_lok_documentGetCommandValues"]=createExportWrapper("lok_documentGetCommandValues",2);var _lok_documentGetPartPageRectangles=Module["_lok_documentGetPartPageRectangles"]=createExportWrapper("lok_documentGetPartPageRectangles",1);var _lok_documentGetPartInfo=Module["_lok_documentGetPartInfo"]=createExportWrapper("lok_documentGetPartInfo",2);var _lok_documentGetPartName=Module["_lok_documentGetPartName"]=createExportWrapper("lok_documentGetPartName",2);var _lok_documentPaste=Module["_lok_documentPaste"]=createExportWrapper("lok_documentPaste",4);var _lok_documentSetClientZoom=Module["_lok_documentSetClientZoom"]=createExportWrapper("lok_documentSetClientZoom",5);var _lok_documentSetClientVisibleArea=Module["_lok_documentSetClientVisibleArea"]=createExportWrapper("lok_documentSetClientVisibleArea",5);var _lok_documentGetA11yFocusedParagraph=Module["_lok_documentGetA11yFocusedParagraph"]=createExportWrapper("lok_documentGetA11yFocusedParagraph",1);var _lok_documentGetA11yCaretPosition=Module["_lok_documentGetA11yCaretPosition"]=createExportWrapper("lok_documentGetA11yCaretPosition",1);var _lok_documentSetAccessibilityState=Module["_lok_documentSetAccessibilityState"]=createExportWrapper("lok_documentSetAccessibilityState",3);var _lok_documentGetDataArea=Module["_lok_documentGetDataArea"]=createExportWrapper("lok_documentGetDataArea",4);var _lok_documentGetEditMode=Module["_lok_documentGetEditMode"]=createExportWrapper("lok_documentGetEditMode",1);var _lok_documentSetEditMode=Module["_lok_documentSetEditMode"]=createExportWrapper("lok_documentSetEditMode",2);var _lok_documentCreateView=Module["_lok_documentCreateView"]=createExportWrapper("lok_documentCreateView",1);var _lok_documentCreateViewWithOptions=Module["_lok_documentCreateViewWithOptions"]=createExportWrapper("lok_documentCreateViewWithOptions",2);var _lok_documentDestroyView=Module["_lok_documentDestroyView"]=createExportWrapper("lok_documentDestroyView",2);var _lok_documentSetView=Module["_lok_documentSetView"]=createExportWrapper("lok_documentSetView",2);var _lok_documentGetView=Module["_lok_documentGetView"]=createExportWrapper("lok_documentGetView",1);var _lok_documentGetViewsCount=Module["_lok_documentGetViewsCount"]=createExportWrapper("lok_documentGetViewsCount",1);var _lok_enableSyncEvents=Module["_lok_enableSyncEvents"]=createExportWrapper("lok_enableSyncEvents",0);var _lok_disableSyncEvents=Module["_lok_disableSyncEvents"]=createExportWrapper("lok_disableSyncEvents",0);var _lok_runLoop=Module["_lok_runLoop"]=createExportWrapper("lok_runLoop",4);var _lok_documentRegisterCallback=Module["_lok_documentRegisterCallback"]=createExportWrapper("lok_documentRegisterCallback",1);var _lok_documentUnregisterCallback=Module["_lok_documentUnregisterCallback"]=createExportWrapper("lok_documentUnregisterCallback",1);var _lok_hasCallbackEvents=Module["_lok_hasCallbackEvents"]=createExportWrapper("lok_hasCallbackEvents",0);var _lok_getCallbackEventCount=Module["_lok_getCallbackEventCount"]=createExportWrapper("lok_getCallbackEventCount",0);var _lok_pollCallback=Module["_lok_pollCallback"]=createExportWrapper("lok_pollCallback",3);var _lok_clearCallbackQueue=Module["_lok_clearCallbackQueue"]=createExportWrapper("lok_clearCallbackQueue",0);var _lok_flushCallbacks=Module["_lok_flushCallbacks"]=createExportWrapper("lok_flushCallbacks",1);var __emscripten_tls_init=createExportWrapper("_emscripten_tls_init",0);var _emscripten_builtin_memalign=createExportWrapper("emscripten_builtin_memalign",2);var __emscripten_proxy_main=Module["__emscripten_proxy_main"]=createExportWrapper("_emscripten_proxy_main",2);var _emscripten_stack_get_base=()=>(_emscripten_stack_get_base=wasmExports["emscripten_stack_get_base"])();var _emscripten_stack_get_end=()=>(_emscripten_stack_get_end=wasmExports["emscripten_stack_get_end"])();var __emscripten_thread_init=createExportWrapper("_emscripten_thread_init",6);var __emscripten_thread_crashed=createExportWrapper("_emscripten_thread_crashed",0);var __emscripten_run_on_main_thread_js=createExportWrapper("_emscripten_run_on_main_thread_js",5);var __emscripten_thread_free_data=createExportWrapper("_emscripten_thread_free_data",1);var __emscripten_thread_exit=createExportWrapper("_emscripten_thread_exit",1);var __emscripten_check_mailbox=createExportWrapper("_emscripten_check_mailbox",0);var ___trap=()=>(___trap=wasmExports["__trap"])();var _emscripten_stack_init=()=>(_emscripten_stack_init=wasmExports["emscripten_stack_init"])();var _emscripten_stack_set_limits=(a0,a1)=>(_emscripten_stack_set_limits=wasmExports["emscripten_stack_set_limits"])(a0,a1);var _emscripten_stack_get_free=()=>(_emscripten_stack_get_free=wasmExports["emscripten_stack_get_free"])();var __emscripten_stack_restore=a0=>(__emscripten_stack_restore=wasmExports["_emscripten_stack_restore"])(a0);var __emscripten_stack_alloc=a0=>(__emscripten_stack_alloc=wasmExports["_emscripten_stack_alloc"])(a0);var _emscripten_stack_get_current=()=>(_emscripten_stack_get_current=wasmExports["emscripten_stack_get_current"])();var ___cxa_decrement_exception_refcount=createExportWrapper("__cxa_decrement_exception_refcount",1);var ___cxa_increment_exception_refcount=createExportWrapper("__cxa_increment_exception_refcount",1);var ___thrown_object_from_unwind_exception=createExportWrapper("__thrown_object_from_unwind_exception",1);var ___get_exception_message=createExportWrapper("__get_exception_message",3);function applySignatureConversions(wasmExports){wasmExports=Object.assign({},wasmExports);var makeWrapper_pp=f=>a0=>f(a0)>>>0;var makeWrapper_p=f=>()=>f()>>>0;var makeWrapper_p_=f=>a0=>f(a0)>>>0;var makeWrapper_ppp=f=>(a0,a1)=>f(a0,a1)>>>0;wasmExports["__getTypeName"]=makeWrapper_pp(wasmExports["__getTypeName"]);wasmExports["malloc"]=makeWrapper_pp(wasmExports["malloc"]);wasmExports["pthread_self"]=makeWrapper_p(wasmExports["pthread_self"]);wasmExports["strerror"]=makeWrapper_p_(wasmExports["strerror"]);wasmExports["emscripten_builtin_memalign"]=makeWrapper_ppp(wasmExports["emscripten_builtin_memalign"]);wasmExports["emscripten_stack_get_base"]=makeWrapper_p(wasmExports["emscripten_stack_get_base"]);wasmExports["emscripten_stack_get_end"]=makeWrapper_p(wasmExports["emscripten_stack_get_end"]);wasmExports["_emscripten_stack_alloc"]=makeWrapper_pp(wasmExports["_emscripten_stack_alloc"]);wasmExports["emscripten_stack_get_current"]=makeWrapper_p(wasmExports["emscripten_stack_get_current"]);return wasmExports}Module["addOnPreMain"]=addOnPreMain;Module["addOnPostRun"]=addOnPostRun;Module["addRunDependency"]=addRunDependency;Module["removeRunDependency"]=removeRunDependency;Module["ENV"]=ENV;Module["wasmTable"]=wasmTable;Module["ccall"]=ccall;Module["cwrap"]=cwrap;Module["UTF8ToString"]=UTF8ToString;Module["UTF16ToString"]=UTF16ToString;Module["stringToUTF16"]=stringToUTF16;Module["FS_createPreloadedFile"]=FS_createPreloadedFile;Module["FS_unlink"]=FS_unlink;Module["FS_createPath"]=FS_createPath;Module["FS_createDevice"]=FS_createDevice;Module["FS"]=FS;Module["FS_createDataFile"]=FS_createDataFile;Module["FS_createLazyFile"]=FS_createLazyFile;Module["throwBindingError"]=throwBindingError;Module["registerType"]=registerType;var missingLibrarySymbols=["writeI53ToI64","writeI53ToI64Clamped","writeI53ToI64Signaling","writeI53ToU64Clamped","writeI53ToU64Signaling","readI53FromU64","convertI32PairToI53","convertI32PairToI53Checked","convertU32PairToI53","getTempRet0","setTempRet0","emscriptenLog","runMainThreadEmAsm","listenOnce","autoResumeAudioContext","asmjsMangle","HandleAllocator","getNativeTypeSize","STACK_SIZE","STACK_ALIGN","POINTER_SIZE","ASSERTIONS","uleb128Encode","sigToWasmTypes","generateFuncType","convertJsFunctionToWasm","getEmptyTableSlot","updateTableMap","getFunctionAddress","addFunction","removeFunction","reallyNegative","unSign","strLen","reSign","formatString","intArrayToString","AsciiToString","stringToNewUTF8","registerKeyEventCallback","maybeCStringToJsString","findEventTarget","getBoundingClientRect","fillMouseEventData","registerMouseEventCallback","registerWheelEventCallback","registerUiEventCallback","registerFocusEventCallback","fillDeviceOrientationEventData","registerDeviceOrientationEventCallback","fillDeviceMotionEventData","registerDeviceMotionEventCallback","screenOrientation","fillOrientationChangeEventData","registerOrientationChangeEventCallback","fillFullscreenChangeEventData","registerFullscreenChangeEventCallback","JSEvents_requestFullscreen","JSEvents_resizeCanvasForFullscreen","registerRestoreOldStyle","hideEverythingExceptGivenElement","restoreHiddenElements","setLetterbox","softFullscreenResizeWebGLRenderTarget","doRequestFullscreen","fillPointerlockChangeEventData","registerPointerlockChangeEventCallback","registerPointerlockErrorEventCallback","requestPointerLock","fillVisibilityChangeEventData","registerVisibilityChangeEventCallback","registerTouchEventCallback","fillGamepadEventData","registerGamepadEventCallback","registerBeforeUnloadEventCallback","fillBatteryEventData","battery","registerBatteryEventCallback","setCanvasElementSizeCallingThread","setCanvasElementSizeMainThread","setCanvasElementSize","getCanvasSizeCallingThread","getCanvasSizeMainThread","getCanvasElementSize","jsStackTrace","getCallstack","convertPCtoSourceLocation","wasiRightsToMuslOFlags","wasiOFlagsToMuslOFlags","safeSetTimeout","setImmediateWrapped","safeRequestAnimationFrame","clearImmediateWrapped","polyfillSetImmediate","registerPostMainLoop","registerPreMainLoop","getPromise","makePromise","idsToPromises","makePromiseCallback","Browser_asyncPrepareDataCounter","arraySum","addDays","FS_mkdirTree","_setNetworkCallback","heapObjectForWebGLType","toTypedArrayIndex","webgl_enable_ANGLE_instanced_arrays","webgl_enable_OES_vertex_array_object","webgl_enable_WEBGL_draw_buffers","webgl_enable_WEBGL_multi_draw","webgl_enable_EXT_polygon_offset_clamp","webgl_enable_EXT_clip_control","webgl_enable_WEBGL_polygon_mode","emscriptenWebGLGet","computeUnpackAlignedImageSize","colorChannelsInGlTextureFormat","emscriptenWebGLGetTexPixelData","emscriptenWebGLGetUniform","webglGetUniformLocation","webglPrepareUniformLocationsBeforeFirstUse","webglGetLeftBracePos","emscriptenWebGLGetVertexAttrib","__glGetActiveAttribOrUniform","writeGLArray","emscripten_webgl_destroy_context_before_on_calling_thread","registerWebGlEventCallback","runAndAbortIfError","ALLOC_NORMAL","ALLOC_STACK","allocate","writeStringToMemory","writeAsciiToMemory","setErrNo","demangle","stackTrace","getFunctionArgsName","createJsInvokerSignature","getInheritedInstanceCount","getLiveInheritedInstances","setDelayFunction","emval_get_global","fetchDeleteCachedData","fetchLoadCachedData","fetchCacheData","fetchXHR"];missingLibrarySymbols.forEach(missingLibrarySymbol);var unexportedSymbols=["run","addOnPreRun","addOnInit","addOnExit","out","err","callMain","abort","wasmMemory","wasmExports","GROWABLE_HEAP_I8","GROWABLE_HEAP_U8","GROWABLE_HEAP_I16","GROWABLE_HEAP_U16","GROWABLE_HEAP_I32","GROWABLE_HEAP_U32","GROWABLE_HEAP_F32","GROWABLE_HEAP_F64","writeStackCookie","checkStackCookie","readI53FromI64","INT53_MAX","INT53_MIN","bigintToI53Checked","stackSave","stackRestore","stackAlloc","ptrToString","zeroMemory","exitJS","getHeapMax","growMemory","ERRNO_CODES","strError","inetPton4","inetNtop4","inetPton6","inetNtop6","readSockaddr","writeSockaddr","DNS","Protocols","Sockets","timers","warnOnce","readEmAsmArgsArray","readEmAsmArgs","runEmAsmFunction","jstoi_q","jstoi_s","getExecutableName","getDynCaller","dynCall","handleException","keepRuntimeAlive","runtimeKeepalivePush","runtimeKeepalivePop","callUserCallback","maybeExit","asyncLoad","alignMemory","mmapAlloc","noExitRuntime","getCFunc","freeTableIndexes","functionsInTableMap","setValue","getValue","PATH","PATH_FS","UTF8Decoder","UTF8ArrayToString","stringToUTF8Array","stringToUTF8","lengthBytesUTF8","intArrayFromString","stringToAscii","UTF16Decoder","lengthBytesUTF16","UTF32ToString","stringToUTF32","lengthBytesUTF32","stringToUTF8OnStack","writeArrayToMemory","JSEvents","specialHTMLTargets","findCanvasEventTarget","currentFullscreenStrategy","restoreOldWindowedStyle","UNWIND_CACHE","ExitStatus","getEnvStrings","checkWasiClock","doReadv","doWritev","initRandomFill","randomFill","promiseMap","getExceptionMessageCommon","getCppExceptionTag","getCppExceptionThrownObjectFromWebAssemblyException","incrementExceptionRefcount","decrementExceptionRefcount","getExceptionMessage","Browser","getPreloadedImageData__data","wget","MONTH_DAYS_REGULAR","MONTH_DAYS_LEAP","MONTH_DAYS_REGULAR_CUMULATIVE","MONTH_DAYS_LEAP_CUMULATIVE","isLeapYear","ydayFromDate","SYSCALLS","getSocketFromFD","getSocketAddress","preloadPlugins","FS_modeStringToFlags","FS_getMode","FS_stdin_getChar_buffer","FS_stdin_getChar","FS_readFile","MEMFS","TTY","PIPEFS","SOCKFS","tempFixedLengthArray","miniTempWebGLFloatBuffers","miniTempWebGLIntBuffers","GL","AL","GLUT","EGL","GLEW","IDBStore","SDL","SDL_gfx","allocateUTF8","allocateUTF8OnStack","print","printErr","PThread","terminateWorker","cleanupThread","registerTLSInit","spawnThread","exitOnMainThread","proxyToMainThread","proxiedJSCallArgs","invokeEntryPoint","checkMailbox","InternalError","BindingError","throwInternalError","registeredTypes","awaitingDependencies","typeDependencies","tupleRegistrations","structRegistrations","sharedRegisterType","whenDependentTypesAreResolved","embind_charCodes","embind_init_charCodes","readLatin1String","getTypeName","getFunctionName","heap32VectorToArray","requireRegisteredType","usesDestructorStack","checkArgCount","getRequiredArgCount","createJsInvoker","UnboundTypeError","PureVirtualError","GenericWireTypeSize","EmValType","EmValOptionalType","throwUnboundTypeError","ensureOverloadTable","exposePublicSymbol","replacePublicSymbol","extendError","createNamedFunction","embindRepr","registeredInstances","getBasestPointer","registerInheritedInstance","unregisterInheritedInstance","getInheritedInstance","registeredPointers","integerReadValueFromPointer","enumReadValueFromPointer","floatReadValueFromPointer","readPointer","runDestructors","newFunc","craftInvokerFunction","embind__requireFunction","genericPointerToWireType","constNoSmartPtrRawPointerToWireType","nonConstNoSmartPtrRawPointerToWireType","init_RegisteredPointer","RegisteredPointer","RegisteredPointer_fromWireType","runDestructor","releaseClassHandle","finalizationRegistry","detachFinalizer_deps","detachFinalizer","attachFinalizer","makeClassHandle","init_ClassHandle","ClassHandle","throwInstanceAlreadyDeleted","deletionQueue","flushPendingDeletes","delayFunction","RegisteredClass","shallowCopyInternalPointer","downcastPointer","upcastPointer","validateThis","char_0","char_9","makeLegalFunctionName","emval_freelist","emval_handles","emval_symbols","init_emval","count_emval_handles","getStringOrSymbol","Emval","emval_returnValue","emval_lookupTypes","emval_methodCallers","emval_addMethodCaller","reflectConstruct","Fetch"];unexportedSymbols.forEach(unexportedRuntimeSymbol);var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function callMain(args=[]){assert(runDependencies==0,'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])');assert(__ATPRERUN__.length==0,"cannot call main when preRun functions remain to be called");var entryFunction=__emscripten_proxy_main;runtimeKeepalivePush();args.unshift(thisProgram);var argc=args.length;var argv=stackAlloc((argc+1)*4);var argv_ptr=argv;args.forEach(arg=>{GROWABLE_HEAP_U32()[argv_ptr>>>2>>>0]=stringToUTF8OnStack(arg);argv_ptr+=4});GROWABLE_HEAP_U32()[argv_ptr>>>2>>>0]=0;try{var ret=entryFunction(argc,argv);exitJS(ret,true);return ret}catch(e){return handleException(e)}}function stackCheckInit(){assert(!ENVIRONMENT_IS_PTHREAD);_emscripten_stack_init();writeStackCookie()}function run(args=arguments_){if(runDependencies>0){return}if(ENVIRONMENT_IS_PTHREAD){initRuntime();return}stackCheckInit();preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();Module["onRuntimeInitialized"]?.();if(shouldRunNow)callMain(args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}checkStackCookie()}function checkUnflushedContent(){var oldOut=out;var oldErr=err;var has=false;out=err=x=>{has=true};try{_fflush(0);["stdout","stderr"].forEach(name=>{var info=FS.analyzePath("/dev/"+name);if(!info)return;var stream=info.object;var rdev=stream.rdev;var tty=TTY.ttys[rdev];if(tty?.output?.length){has=true}})}catch(e){}out=oldOut;err=oldErr;if(has){warnOnce("stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the Emscripten FAQ), or make sure to emit a newline when you printf etc.")}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;run(); diff --git a/public/libreoffice-wasm/soffice.wasm.gz b/public/libreoffice-wasm/soffice.wasm.gz new file mode 100755 index 0000000..8a93838 Binary files /dev/null and b/public/libreoffice-wasm/soffice.wasm.gz differ diff --git a/public/libreoffice-wasm/soffice.worker.js b/public/libreoffice-wasm/soffice.worker.js new file mode 100644 index 0000000..0bd99a5 --- /dev/null +++ b/public/libreoffice-wasm/soffice.worker.js @@ -0,0 +1 @@ +"use strict";var Module={};var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){var nodeWorkerThreads=require("worker_threads");var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",data=>onmessage({data:data}));var fs=require("fs");var vm=require("vm");Object.assign(global,{self:global,require:require,Module:Module,location:{href:__filename},Worker:nodeWorkerThreads.Worker,importScripts:f=>vm.runInThisContext(fs.readFileSync(f,"utf8"),{filename:f}),postMessage:msg=>parentPort.postMessage(msg),performance:global.performance||{now:Date.now}})}var initializedJS=false;function assert(condition,text){if(!condition)abort("Assertion failed: "+text)}function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+"\n");return}console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var out=()=>{throw"out() is not defined in worker.js."};var err=threadPrintErr;self.alert=threadAlert;var dbg=threadPrintErr;Module["instantiateWasm"]=(info,receiveInstance)=>{var module=Module["wasmModule"];Module["wasmModule"]=null;var instance=new WebAssembly.Instance(module,info);return receiveInstance(instance)};self.onunhandledrejection=e=>{throw e.reason||e};function handleMessage(e){try{if(e.data.cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{postMessage({"cmd":"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};Module["wasmModule"]=e.data.wasmModule;for(const handler of e.data.handlers){Module[handler]=(...args)=>{postMessage({cmd:"callHandler",handler:handler,args:args})}}Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["workerID"]=e.data.workerID;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}}else if(e.data.cmd==="run"){Module["__emscripten_thread_init"](e.data.pthread_ptr,0,0,1);Module["__emscripten_thread_mailbox_await"](e.data.pthread_ptr);assert(e.data.pthread_ptr);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInitTLS();if(!initializedJS){Module["__embind_initialize_bindings"]();initializedJS=true}try{Module["invokeEntryPoint"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!="unwind"){throw ex}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="checkMailbox"){if(initializedJS){Module["checkMailbox"]()}}else if(e.data.cmd){err(`worker.js received unknown command ${e.data.cmd}`);err(e.data)}}catch(ex){err(`worker.js onmessage() captured an uncaught exception: ${ex}`);if(ex?.stack){var lines=ex.stack.split("\n").slice(0,10);err(lines.join("\n"))};Module["__emscripten_thread_crashed"]?.();throw ex}}self.onmessage=handleMessage; diff --git a/public/locales/de/common.json b/public/locales/de/common.json index 61d7a42..b128ae3 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -1,318 +1,323 @@ { - "nav": { - "home": "Startseite", - "about": "Über uns", - "contact": "Kontakt", - "licensing": "Lizenzierung", - "allTools": "Alle Werkzeuge", - "openMainMenu": "Hauptmenü öffnen", - "language": "Sprache" + "nav": { + "home": "Startseite", + "about": "Über uns", + "contact": "Kontakt", + "licensing": "Lizenzierung", + "allTools": "Alle Werkzeuge", + "openMainMenu": "Hauptmenü öffnen", + "language": "Sprache" + }, + "donation": { + "message": "Lieben Sie BentoPDF? Helfen Sie uns, es kostenlos und Open Source zu halten!", + "button": "Spenden" + }, + "hero": { + "title": "Das", + "pdfToolkit": "PDF-Toolkit", + "builtForPrivacy": "für maximale Privatsphäre", + "noSignups": "Keine Anmeldung", + "unlimitedUse": "Unbegrenzte Nutzung", + "worksOffline": "Funktioniert offline", + "startUsing": "Jetzt starten" + }, + "usedBy": { + "title": "Verwendet von Unternehmen und Mitarbeitern bei" + }, + "features": { + "title": "Warum", + "bentoPdf": "BentoPDF wählen?", + "noSignup": { + "title": "Keine Anmeldung", + "description": "Sofort starten, keine Konten oder E-Mails erforderlich." }, - "hero": { - "title": "Das", - "pdfToolkit": "PDF-Toolkit", - "builtForPrivacy": "für maximale Privatsphäre", - "noSignups": "Keine Anmeldung", - "unlimitedUse": "Unbegrenzte Nutzung", - "worksOffline": "Funktioniert offline", - "startUsing": "Jetzt starten" + "noUploads": { + "title": "Kein Upload", + "description": "100% clientseitig, Ihre Dateien verlassen nie Ihr Gerät." }, - "usedBy": { - "title": "Verwendet von Unternehmen und Mitarbeitern bei" + "foreverFree": { + "title": "Für immer kostenlos", + "description": "Alle Werkzeuge, keine Testversionen, keine Bezahlschranken." }, - "features": { - "title": "Warum", - "bentoPdf": "BentoPDF wählen?", - "noSignup": { - "title": "Keine Anmeldung", - "description": "Sofort starten, keine Konten oder E-Mails erforderlich." - }, - "noUploads": { - "title": "Kein Upload", - "description": "100% clientseitig, Ihre Dateien verlassen nie Ihr Gerät." - }, - "foreverFree": { - "title": "Für immer kostenlos", - "description": "Alle Werkzeuge, keine Testversionen, keine Bezahlschranken." - }, - "noLimits": { - "title": "Keine Limits", - "description": "Nutzen Sie so viel Sie wollen, ohne versteckte Grenzen." - }, - "batchProcessing": { - "title": "Stapelverarbeitung", - "description": "Verarbeiten Sie unbegrenzt viele PDFs auf einmal." - }, - "lightningFast": { - "title": "Blitzschnell", - "description": "PDFs sofort verarbeiten, ohne Wartezeiten." - } + "noLimits": { + "title": "Keine Limits", + "description": "Nutzen Sie so viel Sie wollen, ohne versteckte Grenzen." }, - "tools": { - "title": "Starten Sie mit", - "toolsLabel": "Werkzeugen", - "subtitle": "Klicken Sie auf ein Werkzeug, um den Datei-Uploader zu öffnen", - "searchPlaceholder": "Werkzeug suchen (z.B. 'teilen', 'organisieren'...)", - "backToTools": "Zurück zu den Werkzeugen" + "batchProcessing": { + "title": "Stapelverarbeitung", + "description": "Verarbeiten Sie unbegrenzt viele PDFs auf einmal." }, - "upload": { - "clickToSelect": "Klicken Sie, um eine Datei auszuwählen", - "orDragAndDrop": "oder per Drag & Drop", - "pdfOrImages": "PDFs oder Bilder", - "filesNeverLeave": "Ihre Dateien verlassen nie Ihr Gerät.", - "addMore": "Weitere Dateien hinzufügen", - "clearAll": "Alle löschen" - }, - "loader": { - "processing": "Verarbeitung..." - }, - "alert": { - "title": "Hinweis", - "ok": "OK" - }, - "preview": { - "title": "Dokumentvorschau", - "downloadAsPdf": "Als PDF herunterladen", - "close": "Schließen" - }, - "settings": { - "title": "Einstellungen", - "shortcuts": "Tastenkürzel", - "preferences": "Voreinstellungen", - "displayPreferences": "Anzeige-Einstellungen", - "searchShortcuts": "Tastenkürzel suchen...", - "shortcutsInfo": "Halten Sie Tasten gedrückt, um ein Kürzel festzulegen. Änderungen werden automatisch gespeichert.", - "shortcutsWarning": "⚠️ Vermeiden Sie gängige Browser-Tastenkürzel (Strg+W, Strg+T, Strg+N usw.), da diese möglicherweise nicht zuverlässig funktionieren.", - "import": "Importieren", - "export": "Exportieren", - "resetToDefaults": "Auf Standard zurücksetzen", - "fullWidthMode": "Vollbreite-Modus", - "fullWidthDescription": "Verwenden Sie die volle Bildschirmbreite für alle Werkzeuge anstelle eines zentrierten Containers", - "settingsAutoSaved": "Einstellungen werden automatisch gespeichert", - "clickToSet": "Klicken zum Festlegen", - "pressKeys": "Tasten drücken...", - "warnings": { - "alreadyInUse": "Tastenkombination bereits vergeben", - "assignedTo": "ist bereits zugewiesen an:", - "chooseDifferent": "Bitte wählen Sie eine andere Tastenkombination.", - "reserved": "Warnung: Reservierte Tastenkombination", - "commonlyUsed": "wird häufig verwendet für:", - "unreliable": "Diese Tastenkombination funktioniert möglicherweise nicht zuverlässig oder könnte mit Browser-/Systemfunktionen in Konflikt geraten.", - "useAnyway": "Möchten Sie sie trotzdem verwenden?", - "resetTitle": "Tastenkombinationen zurücksetzen", - "resetMessage": "Sind Sie sicher, dass Sie alle Tastenkombinationen auf die Standardwerte zurücksetzen möchten?

Diese Aktion kann nicht rückgängig gemacht werden.", - "importSuccessTitle": "Import erfolgreich", - "importSuccessMessage": "Tastenkombinationen erfolgreich importiert!", - "importFailTitle": "Import fehlgeschlagen", - "importFailMessage": "Fehler beim Importieren der Tastenkombinationen. Ungültiges Dateiformat." - } - }, - "warning": { - "title": "Warnung", - "cancel": "Abbrechen", - "proceed": "Fortfahren" - }, - "compliance": { - "title": "Ihre Daten verlassen nie Ihr Gerät", - "weKeep": "Wir schützen", - "yourInfoSafe": "Ihre Informationen", - "byFollowingStandards": "nach globalen Sicherheitsstandards.", - "processingLocal": "Die gesamte Verarbeitung erfolgt lokal auf Ihrem Gerät.", - "gdpr": { - "title": "DSGVO-konform", - "description": "Schützt die personenbezogenen Daten und die Privatsphäre von Personen innerhalb der Europäischen Union." - }, - "ccpa": { - "title": "CCPA-konform", - "description": "Gibt Einwohnern Kaliforniens Rechte darüber, wie ihre persönlichen Daten gesammelt, verwendet und weitergegeben werden." - }, - "hipaa": { - "title": "HIPAA-konform", - "description": "Legt Schutzmaßnahmen für den Umgang mit sensiblen Gesundheitsinformationen im US-Gesundheitssystem fest." - } - }, - "faq": { - "title": "Häufig gestellte", - "questions": "Fragen", - "isFree": { - "question": "Ist BentoPDF wirklich kostenlos?", - "answer": "Ja, absolut. Alle Werkzeuge auf BentoPDF sind zu 100% kostenlos nutzbar, ohne Dateilimits, ohne Anmeldung und ohne Wasserzeichen. Wir glauben, dass jeder Zugang zu einfachen, leistungsstarken PDF-Werkzeugen verdient, ohne Bezahlschranke." - }, - "areFilesSecure": { - "question": "Sind meine Dateien sicher? Wo werden sie verarbeitet?", - "answer": "Ihre Dateien sind so sicher wie möglich, da sie nie Ihren Computer verlassen. Die gesamte Verarbeitung erfolgt direkt in Ihrem Webbrowser (clientseitig). Wir laden Ihre Dateien nie auf einen Server hoch, sodass Sie die vollständige Privatsphäre und Kontrolle über Ihre Dokumente behalten." - }, - "platforms": { - "question": "Funktioniert es auf Mac, Windows und Mobilgeräten?", - "answer": "Ja! Da BentoPDF vollständig in Ihrem Browser läuft, funktioniert es auf jedem Betriebssystem mit einem modernen Webbrowser, einschließlich Windows, macOS, Linux, iOS und Android." - }, - "gdprCompliant": { - "question": "Ist BentoPDF DSGVO-konform?", - "answer": "Ja. BentoPDF ist vollständig DSGVO-konform. Da die gesamte Dateiverarbeitung lokal in Ihrem Browser erfolgt und wir Ihre Dateien nie sammeln oder übertragen, haben wir keinen Zugang zu Ihren Daten. Dies stellt sicher, dass Sie immer die Kontrolle über Ihre Dokumente haben." - }, - "dataStorage": { - "question": "Speichern oder verfolgen Sie meine Dateien?", - "answer": "Nein. Wir speichern, verfolgen oder protokollieren Ihre Dateien niemals. Alles, was Sie auf BentoPDF tun, geschieht im Speicher Ihres Browsers und verschwindet, sobald Sie die Seite schließen. Es gibt keine Uploads, keine Verlaufsprotokolle und keine Server." - }, - "different": { - "question": "Was unterscheidet BentoPDF von anderen PDF-Werkzeugen?", - "answer": "Die meisten PDF-Werkzeuge laden Ihre Dateien zur Verarbeitung auf einen Server hoch. BentoPDF tut das nie. Wir verwenden sichere, moderne Webtechnologie, um Ihre Dateien direkt in Ihrem Browser zu verarbeiten. Das bedeutet schnellere Leistung, stärkere Privatsphäre und vollständige Sicherheit." - }, - "browserBased": { - "question": "Wie schützt mich die browserbasierte Verarbeitung?", - "answer": "Durch die vollständige Ausführung in Ihrem Browser stellt BentoPDF sicher, dass Ihre Dateien nie Ihr Gerät verlassen. Dies eliminiert die Risiken von Server-Hacks, Datenschutzverletzungen oder unbefugtem Zugriff. Ihre Dateien bleiben Ihre — immer." - }, - "analytics": { - "question": "Verwenden Sie Cookies oder Analysen, um mich zu verfolgen?", - "answer": "Uns liegt Ihre Privatsphäre am Herzen. BentoPDF verfolgt keine persönlichen Informationen. Wir verwenden Simple Analytics ausschließlich, um anonyme Besucherzahlen zu sehen. Das bedeutet, wir können wissen, wie viele Benutzer unsere Seite besuchen, aber wir wissen nie, wer Sie sind. Simple Analytics ist vollständig DSGVO-konform und respektiert Ihre Privatsphäre." - } - }, - "testimonials": { - "title": "Was unsere", - "users": "Nutzer", - "say": "sagen" - }, - "support": { - "title": "Gefällt Ihnen meine Arbeit?", - "description": "BentoPDF ist ein Leidenschaftsprojekt, entwickelt um ein kostenloses, privates und leistungsstarkes PDF-Toolkit für alle bereitzustellen. Wenn Sie es nützlich finden, erwägen Sie, die Entwicklung zu unterstützen. Jeder Kaffee hilft!", - "buyMeCoffee": "Kauf mir einen Kaffee" - }, - "footer": { - "copyright": "© 2025 BentoPDF. Alle Rechte vorbehalten.", - "version": "Version", - "company": "Unternehmen", - "aboutUs": "Über uns", - "faqLink": "FAQ", - "contactUs": "Kontakt", - "legal": "Rechtliches", - "termsAndConditions": "Nutzungsbedingungen", - "privacyPolicy": "Datenschutzrichtlinie", - "followUs": "Folgen Sie uns" - }, - "merge": { - "title": "PDFs zusammenführen", - "description": "Kombinieren Sie ganze Dateien oder wählen Sie bestimmte Seiten zum Zusammenführen in ein neues Dokument.", - "fileMode": "Datei-Modus", - "pageMode": "Seiten-Modus", - "howItWorks": "So funktioniert es:", - "fileModeInstructions": [ - "Klicken und ziehen Sie das Symbol, um die Reihenfolge der Dateien zu ändern.", - "Im Feld \"Seiten\" für jede Datei können Sie Bereiche angeben (z.B. \"1-3, 5\"), um nur diese Seiten zusammenzuführen.", - "Lassen Sie das Feld \"Seiten\" leer, um alle Seiten dieser Datei einzuschließen." - ], - "pageModeInstructions": [ - "Alle Seiten Ihrer hochgeladenen PDFs werden unten angezeigt.", - "Ziehen Sie einfach die einzelnen Seitenvorschauen per Drag & Drop, um die gewünschte Reihenfolge für Ihre neue Datei zu erstellen." - ], - "mergePdfs": "PDFs zusammenführen" - }, - "common": { - "page": "Seite", - "pages": "Seiten", - "of": "von", - "download": "Herunterladen", - "cancel": "Abbrechen", - "save": "Speichern", - "delete": "Löschen", - "edit": "Bearbeiten", - "add": "Hinzufügen", - "remove": "Entfernen", - "loading": "Laden...", - "error": "Fehler", - "success": "Erfolg", - "file": "Datei", - "files": "Dateien" - }, - "about": { - "hero": { - "title": "Wir glauben PDF-Werkzeuge sollten", - "subtitle": "schnell, privat und kostenlos sein.", - "noCompromises": "Ohne Kompromisse." - }, - "mission": { - "title": "Unsere Mission", - "description": "Die umfassendste PDF-Toolbox bereitzustellen, die Ihre Privatsphäre respektiert und niemals eine Bezahlung verlangt. Wir glauben, dass wichtige Dokumentenwerkzeuge für jeden, überall und ohne Barrieren zugänglich sein sollten." - }, - "philosophy": { - "label": "Unsere Kernphilosophie", - "title": "Privatsphäre zuerst. Immer.", - "description": "In einer Zeit, in der Daten eine Ware sind, gehen wir einen anderen Weg. Die gesamte Verarbeitung für Bentopdf-Werkzeuge erfolgt lokal in Ihrem Browser. Das bedeutet, Ihre Dateien berühren niemals unsere Server, wir sehen Ihre Dokumente nie und verfolgen nicht, was Sie tun. Ihre Dokumente bleiben vollständig und unmissverständlich privat. Es ist nicht nur eine Funktion; es ist unser Fundament." - }, - "whyBentopdf": { - "title": "Warum", - "speed": { - "title": "Für Geschwindigkeit gebaut", - "description": "Kein Warten auf Uploads oder Downloads zu einem Server. Durch die Verarbeitung von Dateien direkt in Ihrem Browser mit modernen Webtechnologien wie WebAssembly bieten wir unvergleichliche Geschwindigkeit für alle unsere Werkzeuge." - }, - "free": { - "title": "Komplett kostenlos", - "description": "Keine Testversionen, keine Abonnements, keine versteckten Gebühren und keine \"Premium\"-Funktionen als Geiseln. Wir glauben, leistungsstarke PDF-Werkzeuge sollten ein öffentliches Gut sein, kein Profitcenter." - }, - "noAccount": { - "title": "Kein Konto erforderlich", - "description": "Beginnen Sie sofort mit der Nutzung eines beliebigen Werkzeugs. Wir brauchen weder Ihre E-Mail noch ein Passwort oder persönliche Informationen. Ihr Workflow sollte reibungslos und anonym sein." - }, - "openSource": { - "title": "Open-Source-Geist", - "description": "Mit Transparenz im Blick entwickelt. Wir nutzen großartige Open-Source-Bibliotheken wie PDF-lib und PDF.js und glauben an die gemeinschaftsgetriebene Bemühung, leistungsstarke Werkzeuge für alle zugänglich zu machen." - } - }, - "cta": { - "title": "Bereit loszulegen?", - "description": "Schließen Sie sich Tausenden von Benutzern an, die Bentopdf für ihre täglichen Dokumentenbedürfnisse vertrauen. Erleben Sie den Unterschied, den Privatsphäre und Leistung machen können.", - "button": "Alle Werkzeuge erkunden" - } - }, - "contact": { - "title": "Kontakt aufnehmen", - "subtitle": "Wir freuen uns, von Ihnen zu hören. Ob Sie eine Frage, Feedback oder eine Funktionsanfrage haben, zögern Sie nicht, uns zu kontaktieren.", - "email": "Sie können uns direkt per E-Mail erreichen unter:" - }, - "licensing": { - "title": "Lizenzierung für", - "subtitle": "Wählen Sie die Lizenz, die Ihren Anforderungen entspricht." - }, - "multiTool": { - "uploadPdfs": "PDFs hochladen", - "upload": "Hochladen", - "addBlankPage": "Leere Seite hinzufügen", - "edit": "Bearbeiten:", - "undo": "Rückgängig", - "redo": "Wiederholen", - "reset": "Zurücksetzen", - "selection": "Auswahl:", - "selectAll": "Alles auswählen", - "deselectAll": "Auswahl aufheben", - "rotate": "Drehen:", - "rotateLeft": "Links", - "rotateRight": "Rechts", - "transform": "Transformieren:", - "duplicate": "Duplizieren", - "split": "Teilen", - "clear": "Löschen:", - "delete": "Entfernen", - "download": "Download:", - "downloadSelected": "Auswahl herunterladen", - "exportPdf": "PDF exportieren", - "uploadPdfFiles": "PDF-Dateien auswählen", - "dragAndDrop": "PDF-Dateien hierhin ziehen oder klicken zum Auswählen", - "selectFiles": "Dateien auswählen", - "renderingPages": "Seiten werden gerendert...", - "actions": { - "duplicatePage": "Diese Seite duplizieren", - "deletePage": "Diese Seite löschen", - "insertPdf": "PDF nach dieser Seite einfügen", - "toggleSplit": "Trennung nach dieser Seite umschalten" - }, - "pleaseWait": "Bitte warten", - "pagesRendering": "Seiten werden noch gerendert. Bitte warten...", - "noPagesSelected": "Keine Seiten ausgewählt", - "selectOnePage": "Bitte wählen Sie mindestens eine Seite zum Herunterladen aus.", - "noPages": "Keine Seiten", - "noPagesToExport": "Keine Seiten zum Exportieren vorhanden.", - "renderingTitle": "Seiten-Vorschau wird gerendert", - "errorRendering": "Fehler beim Rendern der Seitenvorschau", - "error": "Fehler", - "failedToLoad": "Laden fehlgeschlagen" + "lightningFast": { + "title": "Blitzschnell", + "description": "PDFs sofort verarbeiten, ohne Wartezeiten." } -} \ No newline at end of file + }, + "tools": { + "title": "Starten Sie mit", + "toolsLabel": "Werkzeugen", + "subtitle": "Klicken Sie auf ein Werkzeug, um den Datei-Uploader zu öffnen", + "searchPlaceholder": "Werkzeug suchen (z.B. 'teilen', 'organisieren'...)", + "backToTools": "Zurück zu den Werkzeugen", + "firstLoadNotice": "Der erste Ladevorgang dauert einen Moment, da wir unsere Konvertierungs-Engine herunterladen. Danach erfolgt jedes Laden sofort." + }, + "upload": { + "clickToSelect": "Klicken Sie, um eine Datei auszuwählen", + "orDragAndDrop": "oder per Drag & Drop", + "pdfOrImages": "PDFs oder Bilder", + "filesNeverLeave": "Ihre Dateien verlassen nie Ihr Gerät.", + "addMore": "Weitere Dateien hinzufügen", + "clearAll": "Alle löschen" + }, + "loader": { + "processing": "Verarbeitung..." + }, + "alert": { + "title": "Hinweis", + "ok": "OK" + }, + "preview": { + "title": "Dokumentvorschau", + "downloadAsPdf": "Als PDF herunterladen", + "close": "Schließen" + }, + "settings": { + "title": "Einstellungen", + "shortcuts": "Tastenkürzel", + "preferences": "Voreinstellungen", + "displayPreferences": "Anzeige-Einstellungen", + "searchShortcuts": "Tastenkürzel suchen...", + "shortcutsInfo": "Halten Sie Tasten gedrückt, um ein Kürzel festzulegen. Änderungen werden automatisch gespeichert.", + "shortcutsWarning": "⚠️ Vermeiden Sie gängige Browser-Tastenkürzel (Strg+W, Strg+T, Strg+N usw.), da diese möglicherweise nicht zuverlässig funktionieren.", + "import": "Importieren", + "export": "Exportieren", + "resetToDefaults": "Auf Standard zurücksetzen", + "fullWidthMode": "Vollbreite-Modus", + "fullWidthDescription": "Verwenden Sie die volle Bildschirmbreite für alle Werkzeuge anstelle eines zentrierten Containers", + "settingsAutoSaved": "Einstellungen werden automatisch gespeichert", + "clickToSet": "Klicken zum Festlegen", + "pressKeys": "Tasten drücken...", + "warnings": { + "alreadyInUse": "Tastenkombination bereits vergeben", + "assignedTo": "ist bereits zugewiesen an:", + "chooseDifferent": "Bitte wählen Sie eine andere Tastenkombination.", + "reserved": "Warnung: Reservierte Tastenkombination", + "commonlyUsed": "wird häufig verwendet für:", + "unreliable": "Diese Tastenkombination funktioniert möglicherweise nicht zuverlässig oder könnte mit Browser-/Systemfunktionen in Konflikt geraten.", + "useAnyway": "Möchten Sie sie trotzdem verwenden?", + "resetTitle": "Tastenkombinationen zurücksetzen", + "resetMessage": "Sind Sie sicher, dass Sie alle Tastenkombinationen auf die Standardwerte zurücksetzen möchten?

Diese Aktion kann nicht rückgängig gemacht werden.", + "importSuccessTitle": "Import erfolgreich", + "importSuccessMessage": "Tastenkombinationen erfolgreich importiert!", + "importFailTitle": "Import fehlgeschlagen", + "importFailMessage": "Fehler beim Importieren der Tastenkombinationen. Ungültiges Dateiformat." + } + }, + "warning": { + "title": "Warnung", + "cancel": "Abbrechen", + "proceed": "Fortfahren" + }, + "compliance": { + "title": "Ihre Daten verlassen nie Ihr Gerät", + "weKeep": "Wir schützen", + "yourInfoSafe": "Ihre Informationen", + "byFollowingStandards": "nach globalen Sicherheitsstandards.", + "processingLocal": "Die gesamte Verarbeitung erfolgt lokal auf Ihrem Gerät.", + "gdpr": { + "title": "DSGVO-konform", + "description": "Schützt die personenbezogenen Daten und die Privatsphäre von Personen innerhalb der Europäischen Union." + }, + "ccpa": { + "title": "CCPA-konform", + "description": "Gibt Einwohnern Kaliforniens Rechte darüber, wie ihre persönlichen Daten gesammelt, verwendet und weitergegeben werden." + }, + "hipaa": { + "title": "HIPAA-konform", + "description": "Legt Schutzmaßnahmen für den Umgang mit sensiblen Gesundheitsinformationen im US-Gesundheitssystem fest." + } + }, + "faq": { + "title": "Häufig gestellte", + "questions": "Fragen", + "isFree": { + "question": "Ist BentoPDF wirklich kostenlos?", + "answer": "Ja, absolut. Alle Werkzeuge auf BentoPDF sind zu 100% kostenlos nutzbar, ohne Dateilimits, ohne Anmeldung und ohne Wasserzeichen. Wir glauben, dass jeder Zugang zu einfachen, leistungsstarken PDF-Werkzeugen verdient, ohne Bezahlschranke." + }, + "areFilesSecure": { + "question": "Sind meine Dateien sicher? Wo werden sie verarbeitet?", + "answer": "Ihre Dateien sind so sicher wie möglich, da sie nie Ihren Computer verlassen. Die gesamte Verarbeitung erfolgt direkt in Ihrem Webbrowser (clientseitig). Wir laden Ihre Dateien nie auf einen Server hoch, sodass Sie die vollständige Privatsphäre und Kontrolle über Ihre Dokumente behalten." + }, + "platforms": { + "question": "Funktioniert es auf Mac, Windows und Mobilgeräten?", + "answer": "Ja! Da BentoPDF vollständig in Ihrem Browser läuft, funktioniert es auf jedem Betriebssystem mit einem modernen Webbrowser, einschließlich Windows, macOS, Linux, iOS und Android." + }, + "gdprCompliant": { + "question": "Ist BentoPDF DSGVO-konform?", + "answer": "Ja. BentoPDF ist vollständig DSGVO-konform. Da die gesamte Dateiverarbeitung lokal in Ihrem Browser erfolgt und wir Ihre Dateien nie sammeln oder übertragen, haben wir keinen Zugang zu Ihren Daten. Dies stellt sicher, dass Sie immer die Kontrolle über Ihre Dokumente haben." + }, + "dataStorage": { + "question": "Speichern oder verfolgen Sie meine Dateien?", + "answer": "Nein. Wir speichern, verfolgen oder protokollieren Ihre Dateien niemals. Alles, was Sie auf BentoPDF tun, geschieht im Speicher Ihres Browsers und verschwindet, sobald Sie die Seite schließen. Es gibt keine Uploads, keine Verlaufsprotokolle und keine Server." + }, + "different": { + "question": "Was unterscheidet BentoPDF von anderen PDF-Werkzeugen?", + "answer": "Die meisten PDF-Werkzeuge laden Ihre Dateien zur Verarbeitung auf einen Server hoch. BentoPDF tut das nie. Wir verwenden sichere, moderne Webtechnologie, um Ihre Dateien direkt in Ihrem Browser zu verarbeiten. Das bedeutet schnellere Leistung, stärkere Privatsphäre und vollständige Sicherheit." + }, + "browserBased": { + "question": "Wie schützt mich die browserbasierte Verarbeitung?", + "answer": "Durch die vollständige Ausführung in Ihrem Browser stellt BentoPDF sicher, dass Ihre Dateien nie Ihr Gerät verlassen. Dies eliminiert die Risiken von Server-Hacks, Datenschutzverletzungen oder unbefugtem Zugriff. Ihre Dateien bleiben Ihre — immer." + }, + "analytics": { + "question": "Verwenden Sie Cookies oder Analysen, um mich zu verfolgen?", + "answer": "Uns liegt Ihre Privatsphäre am Herzen. BentoPDF verfolgt keine persönlichen Informationen. Wir verwenden Simple Analytics ausschließlich, um anonyme Besucherzahlen zu sehen. Das bedeutet, wir können wissen, wie viele Benutzer unsere Seite besuchen, aber wir wissen nie, wer Sie sind. Simple Analytics ist vollständig DSGVO-konform und respektiert Ihre Privatsphäre." + } + }, + "testimonials": { + "title": "Was unsere", + "users": "Nutzer", + "say": "sagen" + }, + "support": { + "title": "Gefällt Ihnen meine Arbeit?", + "description": "BentoPDF ist ein Leidenschaftsprojekt, entwickelt um ein kostenloses, privates und leistungsstarkes PDF-Toolkit für alle bereitzustellen. Wenn Sie es nützlich finden, erwägen Sie, die Entwicklung zu unterstützen. Jeder Kaffee hilft!", + "buyMeCoffee": "Kauf mir einen Kaffee" + }, + "footer": { + "copyright": "© 2026 BentoPDF. Alle Rechte vorbehalten.", + "version": "Version", + "company": "Unternehmen", + "aboutUs": "Über uns", + "faqLink": "FAQ", + "contactUs": "Kontakt", + "legal": "Rechtliches", + "termsAndConditions": "Nutzungsbedingungen", + "privacyPolicy": "Datenschutzrichtlinie", + "followUs": "Folgen Sie uns" + }, + "merge": { + "title": "PDFs zusammenführen", + "description": "Kombinieren Sie ganze Dateien oder wählen Sie bestimmte Seiten zum Zusammenführen in ein neues Dokument.", + "fileMode": "Datei-Modus", + "pageMode": "Seiten-Modus", + "howItWorks": "So funktioniert es:", + "fileModeInstructions": [ + "Klicken und ziehen Sie das Symbol, um die Reihenfolge der Dateien zu ändern.", + "Im Feld \"Seiten\" für jede Datei können Sie Bereiche angeben (z.B. \"1-3, 5\"), um nur diese Seiten zusammenzuführen.", + "Lassen Sie das Feld \"Seiten\" leer, um alle Seiten dieser Datei einzuschließen." + ], + "pageModeInstructions": [ + "Alle Seiten Ihrer hochgeladenen PDFs werden unten angezeigt.", + "Ziehen Sie einfach die einzelnen Seitenvorschauen per Drag & Drop, um die gewünschte Reihenfolge für Ihre neue Datei zu erstellen." + ], + "mergePdfs": "PDFs zusammenführen" + }, + "common": { + "page": "Seite", + "pages": "Seiten", + "of": "von", + "download": "Herunterladen", + "cancel": "Abbrechen", + "save": "Speichern", + "delete": "Löschen", + "edit": "Bearbeiten", + "add": "Hinzufügen", + "remove": "Entfernen", + "loading": "Laden...", + "error": "Fehler", + "success": "Erfolg", + "file": "Datei", + "files": "Dateien" + }, + "about": { + "hero": { + "title": "Wir glauben PDF-Werkzeuge sollten", + "subtitle": "schnell, privat und kostenlos sein.", + "noCompromises": "Ohne Kompromisse." + }, + "mission": { + "title": "Unsere Mission", + "description": "Die umfassendste PDF-Toolbox bereitzustellen, die Ihre Privatsphäre respektiert und niemals eine Bezahlung verlangt. Wir glauben, dass wichtige Dokumentenwerkzeuge für jeden, überall und ohne Barrieren zugänglich sein sollten." + }, + "philosophy": { + "label": "Unsere Kernphilosophie", + "title": "Privatsphäre zuerst. Immer.", + "description": "In einer Zeit, in der Daten eine Ware sind, gehen wir einen anderen Weg. Die gesamte Verarbeitung für Bentopdf-Werkzeuge erfolgt lokal in Ihrem Browser. Das bedeutet, Ihre Dateien berühren niemals unsere Server, wir sehen Ihre Dokumente nie und verfolgen nicht, was Sie tun. Ihre Dokumente bleiben vollständig und unmissverständlich privat. Es ist nicht nur eine Funktion; es ist unser Fundament." + }, + "whyBentopdf": { + "title": "Warum", + "speed": { + "title": "Für Geschwindigkeit gebaut", + "description": "Kein Warten auf Uploads oder Downloads zu einem Server. Durch die Verarbeitung von Dateien direkt in Ihrem Browser mit modernen Webtechnologien wie WebAssembly bieten wir unvergleichliche Geschwindigkeit für alle unsere Werkzeuge." + }, + "free": { + "title": "Komplett kostenlos", + "description": "Keine Testversionen, keine Abonnements, keine versteckten Gebühren und keine \"Premium\"-Funktionen als Geiseln. Wir glauben, leistungsstarke PDF-Werkzeuge sollten ein öffentliches Gut sein, kein Profitcenter." + }, + "noAccount": { + "title": "Kein Konto erforderlich", + "description": "Beginnen Sie sofort mit der Nutzung eines beliebigen Werkzeugs. Wir brauchen weder Ihre E-Mail noch ein Passwort oder persönliche Informationen. Ihr Workflow sollte reibungslos und anonym sein." + }, + "openSource": { + "title": "Open-Source-Geist", + "description": "Mit Transparenz im Blick entwickelt. Wir nutzen großartige Open-Source-Bibliotheken wie PDF-lib und PDF.js und glauben an die gemeinschaftsgetriebene Bemühung, leistungsstarke Werkzeuge für alle zugänglich zu machen." + } + }, + "cta": { + "title": "Bereit loszulegen?", + "description": "Schließen Sie sich Tausenden von Benutzern an, die Bentopdf für ihre täglichen Dokumentenbedürfnisse vertrauen. Erleben Sie den Unterschied, den Privatsphäre und Leistung machen können.", + "button": "Alle Werkzeuge erkunden" + } + }, + "contact": { + "title": "Kontakt aufnehmen", + "subtitle": "Wir freuen uns, von Ihnen zu hören. Ob Sie eine Frage, Feedback oder eine Funktionsanfrage haben, zögern Sie nicht, uns zu kontaktieren.", + "email": "Sie können uns direkt per E-Mail erreichen unter:" + }, + "licensing": { + "title": "Lizenzierung für", + "subtitle": "Wählen Sie die Lizenz, die Ihren Anforderungen entspricht." + }, + "multiTool": { + "uploadPdfs": "PDFs hochladen", + "upload": "Hochladen", + "addBlankPage": "Leere Seite hinzufügen", + "edit": "Bearbeiten:", + "undo": "Rückgängig", + "redo": "Wiederholen", + "reset": "Zurücksetzen", + "selection": "Auswahl:", + "selectAll": "Alles auswählen", + "deselectAll": "Auswahl aufheben", + "rotate": "Drehen:", + "rotateLeft": "Links", + "rotateRight": "Rechts", + "transform": "Transformieren:", + "duplicate": "Duplizieren", + "split": "Teilen", + "clear": "Löschen:", + "delete": "Entfernen", + "download": "Download:", + "downloadSelected": "Auswahl herunterladen", + "exportPdf": "PDF exportieren", + "uploadPdfFiles": "PDF-Dateien auswählen", + "dragAndDrop": "PDF-Dateien hierhin ziehen oder klicken zum Auswählen", + "selectFiles": "Dateien auswählen", + "renderingPages": "Seiten werden gerendert...", + "actions": { + "duplicatePage": "Diese Seite duplizieren", + "deletePage": "Diese Seite löschen", + "insertPdf": "PDF nach dieser Seite einfügen", + "toggleSplit": "Trennung nach dieser Seite umschalten" + }, + "pleaseWait": "Bitte warten", + "pagesRendering": "Seiten werden noch gerendert. Bitte warten...", + "noPagesSelected": "Keine Seiten ausgewählt", + "selectOnePage": "Bitte wählen Sie mindestens eine Seite zum Herunterladen aus.", + "noPages": "Keine Seiten", + "noPagesToExport": "Keine Seiten zum Exportieren vorhanden.", + "renderingTitle": "Seiten-Vorschau wird gerendert", + "errorRendering": "Fehler beim Rendern der Seitenvorschau", + "error": "Fehler", + "failedToLoad": "Laden fehlgeschlagen" + } +} diff --git a/public/locales/de/tools.json b/public/locales/de/tools.json index 9aed2ce..769e591 100644 --- a/public/locales/de/tools.json +++ b/public/locales/de/tools.json @@ -1,282 +1,533 @@ { - "categories": { - "popularTools": "Beliebte Werkzeuge", - "editAnnotate": "Bearbeiten & Annotieren", - "convertToPdf": "In PDF konvertieren", - "convertFromPdf": "Aus PDF konvertieren", - "organizeManage": "Organisieren & Verwalten", - "optimizeRepair": "Optimieren & Reparieren", - "securePdf": "PDF sichern" - }, - "pdfMultiTool": { - "name": "PDF Multi-Werkzeug", - "subtitle": "Zusammenführen, Teilen, Organisieren, Löschen, Drehen, Leere Seiten hinzufügen, Extrahieren und Duplizieren in einer einheitlichen Oberfläche." - }, - "mergePdf": { - "name": "PDF zusammenführen", - "subtitle": "Mehrere PDFs zu einer Datei kombinieren. Lesezeichen werden beibehalten." - }, - "splitPdf": { - "name": "PDF teilen", - "subtitle": "Einen Seitenbereich in eine neue PDF extrahieren." - }, - "compressPdf": { - "name": "PDF komprimieren", - "subtitle": "Die Dateigröße Ihrer PDF reduzieren." - }, - "pdfEditor": { - "name": "PDF-Editor", - "subtitle": "Annotieren, hervorheben, schwärzen, kommentieren, Formen/Bilder hinzufügen, suchen und PDFs anzeigen." - }, - "jpgToPdf": { - "name": "JPG zu PDF", - "subtitle": "Eine PDF aus einem oder mehreren JPG-Bildern erstellen." - }, - "signPdf": { - "name": "PDF unterschreiben", - "subtitle": "Zeichnen, tippen oder laden Sie Ihre Unterschrift hoch." - }, - "cropPdf": { - "name": "PDF zuschneiden", - "subtitle": "Die Ränder jeder Seite in Ihrer PDF beschneiden." - }, - "extractPages": { - "name": "Seiten extrahieren", - "subtitle": "Eine Auswahl von Seiten als neue Dateien speichern." - }, - "duplicateOrganize": { - "name": "Duplizieren & Organisieren", - "subtitle": "Seiten duplizieren, neu anordnen und löschen." - }, - "deletePages": { - "name": "Seiten löschen", - "subtitle": "Bestimmte Seiten aus Ihrem Dokument entfernen." - }, - "editBookmarks": { - "name": "Lesezeichen bearbeiten", - "subtitle": "PDF-Lesezeichen hinzufügen, bearbeiten, importieren, löschen und extrahieren." - }, - "tableOfContents": { - "name": "Inhaltsverzeichnis", - "subtitle": "Ein Inhaltsverzeichnis aus PDF-Lesezeichen generieren." - }, - "pageNumbers": { - "name": "Seitenzahlen", - "subtitle": "Seitenzahlen in Ihr Dokument einfügen." - }, - "addWatermark": { - "name": "Wasserzeichen hinzufügen", - "subtitle": "Text oder ein Bild über Ihre PDF-Seiten stempeln." - }, - "headerFooter": { - "name": "Kopf- & Fußzeile", - "subtitle": "Text oben und unten auf Seiten hinzufügen." - }, - "invertColors": { - "name": "Farben invertieren", - "subtitle": "Eine \"Dunkelmodus\"-Version Ihrer PDF erstellen." - }, - "backgroundColor": { - "name": "Hintergrundfarbe", - "subtitle": "Die Hintergrundfarbe Ihrer PDF ändern." - }, - "changeTextColor": { - "name": "Textfarbe ändern", - "subtitle": "Die Farbe des Textes in Ihrer PDF ändern." - }, - "addStamps": { - "name": "Stempel hinzufügen", - "subtitle": "Bildstempel zu Ihrer PDF über die Annotations-Symbolleiste hinzufügen.", - "usernameLabel": "Stempel-Benutzername", - "usernamePlaceholder": "Geben Sie Ihren Namen ein (für Stempel)", - "usernameHint": "Dieser Name erscheint auf von Ihnen erstellten Stempeln." - }, - "removeAnnotations": { - "name": "Annotationen entfernen", - "subtitle": "Kommentare, Hervorhebungen und Links entfernen." - }, - "pdfFormFiller": { - "name": "PDF-Formular ausfüllen", - "subtitle": "Formulare direkt im Browser ausfüllen. Unterstützt auch XFA-Formulare." - }, - "createPdfForm": { - "name": "PDF-Formular erstellen", - "subtitle": "Ausfüllbare PDF-Formulare mit Drag-and-Drop-Textfeldern erstellen." - }, - "removeBlankPages": { - "name": "Leere Seiten entfernen", - "subtitle": "Leere Seiten automatisch erkennen und löschen." - }, - "imageToPdf": { - "name": "Bild zu PDF", - "subtitle": "JPG, PNG, WebP, BMP, TIFF, SVG, HEIC in PDF konvertieren." - }, - "pngToPdf": { - "name": "PNG zu PDF", - "subtitle": "Eine PDF aus einem oder mehreren PNG-Bildern erstellen." - }, - "webpToPdf": { - "name": "WebP zu PDF", - "subtitle": "Eine PDF aus einem oder mehreren WebP-Bildern erstellen." - }, - "svgToPdf": { - "name": "SVG zu PDF", - "subtitle": "Eine PDF aus einem oder mehreren SVG-Bildern erstellen." - }, - "bmpToPdf": { - "name": "BMP zu PDF", - "subtitle": "Eine PDF aus einem oder mehreren BMP-Bildern erstellen." - }, - "heicToPdf": { - "name": "HEIC zu PDF", - "subtitle": "Eine PDF aus einem oder mehreren HEIC-Bildern erstellen." - }, - "tiffToPdf": { - "name": "TIFF zu PDF", - "subtitle": "Eine PDF aus einem oder mehreren TIFF-Bildern erstellen." - }, - "textToPdf": { - "name": "Text zu PDF", - "subtitle": "Eine Textdatei in eine PDF konvertieren." - }, - "jsonToPdf": { - "name": "JSON zu PDF", - "subtitle": "JSON-Dateien in PDF-Format konvertieren." - }, - "pdfToJpg": { - "name": "PDF zu JPG", - "subtitle": "Jede PDF-Seite in ein JPG-Bild konvertieren." - }, - "pdfToPng": { - "name": "PDF zu PNG", - "subtitle": "Jede PDF-Seite in ein PNG-Bild konvertieren." - }, - "pdfToWebp": { - "name": "PDF zu WebP", - "subtitle": "Jede PDF-Seite in ein WebP-Bild konvertieren." - }, - "pdfToBmp": { - "name": "PDF zu BMP", - "subtitle": "Jede PDF-Seite in ein BMP-Bild konvertieren." - }, - "pdfToTiff": { - "name": "PDF zu TIFF", - "subtitle": "Jede PDF-Seite in ein TIFF-Bild konvertieren." - }, - "pdfToGreyscale": { - "name": "PDF zu Graustufen", - "subtitle": "Alle Farben in Schwarz-Weiß konvertieren." - }, - "pdfToJson": { - "name": "PDF zu JSON", - "subtitle": "PDF-Dateien in JSON-Format konvertieren." - }, - "ocrPdf": { - "name": "OCR PDF", - "subtitle": "Eine PDF durchsuchbar und kopierbar machen." - }, - "alternateMix": { - "name": "Seiten abwechselnd mischen", - "subtitle": "PDFs durch abwechselnde Seiten aus jedem PDF zusammenführen. Lesezeichen werden beibehalten." - }, - "addAttachments": { - "name": "Anhänge hinzufügen", - "subtitle": "Eine oder mehrere Dateien in Ihre PDF einbetten." - }, - "extractAttachments": { - "name": "Anhänge extrahieren", - "subtitle": "Alle eingebetteten Dateien aus PDF(s) als ZIP extrahieren." - }, - "editAttachments": { - "name": "Anhänge bearbeiten", - "subtitle": "Anhänge in Ihrer PDF anzeigen oder entfernen." - }, - "dividePages": { - "name": "Seiten teilen", - "subtitle": "Seiten horizontal oder vertikal teilen." - }, - "addBlankPage": { - "name": "Leere Seite hinzufügen", - "subtitle": "Eine leere Seite an beliebiger Stelle in Ihre PDF einfügen." - }, - "reversePages": { - "name": "Seiten umkehren", - "subtitle": "Die Reihenfolge aller Seiten in Ihrem Dokument umkehren." - }, - "rotatePdf": { - "name": "PDF drehen", - "subtitle": "Seiten in 90-Grad-Schritten drehen." - }, - "nUpPdf": { - "name": "N-Up PDF", - "subtitle": "Mehrere Seiten auf einem einzigen Blatt anordnen." - }, - "combineToSinglePage": { - "name": "Zu einer Seite kombinieren", - "subtitle": "Alle Seiten zu einem fortlaufenden Dokument zusammenfügen." - }, - "viewMetadata": { - "name": "Metadaten anzeigen", - "subtitle": "Die versteckten Eigenschaften Ihrer PDF inspizieren." - }, - "editMetadata": { - "name": "Metadaten bearbeiten", - "subtitle": "Autor, Titel und andere Eigenschaften ändern." - }, - "pdfsToZip": { - "name": "PDFs zu ZIP", - "subtitle": "Mehrere PDF-Dateien in ein ZIP-Archiv packen." - }, - "comparePdfs": { - "name": "PDFs vergleichen", - "subtitle": "Zwei PDFs nebeneinander vergleichen." - }, - "posterizePdf": { - "name": "PDF posterisieren", - "subtitle": "Eine große Seite in mehrere kleinere Seiten aufteilen." - }, - "fixPageSize": { - "name": "Seitengröße reparieren", - "subtitle": "Alle Seiten auf eine einheitliche Größe standardisieren." - }, - "linearizePdf": { - "name": "PDF linearisieren", - "subtitle": "PDF für schnelle Web-Anzeige optimieren." - }, - "pageDimensions": { - "name": "Seitenmaße", - "subtitle": "Seitengröße, Ausrichtung und Einheiten analysieren." - }, - "removeRestrictions": { - "name": "Beschränkungen entfernen", - "subtitle": "Passwortschutz und Sicherheitsbeschränkungen von digital signierten PDF-Dateien entfernen." - }, - "repairPdf": { - "name": "PDF reparieren", - "subtitle": "Daten aus beschädigten PDF-Dateien wiederherstellen." - }, - "encryptPdf": { - "name": "PDF verschlüsseln", - "subtitle": "Ihre PDF durch Hinzufügen eines Passworts sperren." - }, - "sanitizePdf": { - "name": "PDF bereinigen", - "subtitle": "Metadaten, Annotationen, Skripte und mehr entfernen." - }, - "decryptPdf": { - "name": "PDF entschlüsseln", - "subtitle": "PDF durch Entfernen des Passwortschutzes entsperren." - }, - "flattenPdf": { - "name": "PDF reduzieren", - "subtitle": "Formularfelder und Annotationen nicht editierbar machen." - }, - "removeMetadata": { - "name": "Metadaten entfernen", - "subtitle": "Versteckte Daten aus Ihrer PDF entfernen." - }, - "changePermissions": { - "name": "Berechtigungen ändern", - "subtitle": "Benutzerberechtigungen für eine PDF festlegen oder ändern." - } -} \ No newline at end of file + "categories": { + "popularTools": "Beliebte Werkzeuge", + "editAnnotate": "Bearbeiten & Annotieren", + "convertToPdf": "In PDF konvertieren", + "convertFromPdf": "Aus PDF konvertieren", + "organizeManage": "Organisieren & Verwalten", + "optimizeRepair": "Optimieren & Reparieren", + "securePdf": "PDF sichern" + }, + "pdfMultiTool": { + "name": "PDF Multi-Werkzeug", + "subtitle": "Zusammenführen, Teilen, Organisieren, Löschen, Drehen, Leere Seiten hinzufügen, Extrahieren und Duplizieren in einer einheitlichen Oberfläche." + }, + "mergePdf": { + "name": "PDF zusammenführen", + "subtitle": "Mehrere PDFs zu einer Datei kombinieren. Lesezeichen werden beibehalten." + }, + "splitPdf": { + "name": "PDF teilen", + "subtitle": "Einen Seitenbereich in eine neue PDF extrahieren." + }, + "compressPdf": { + "name": "PDF komprimieren", + "subtitle": "Die Dateigröße Ihrer PDF reduzieren.", + "algorithmLabel": "Komprimierungsalgorithmus", + "condense": "Condense (Empfohlen)", + "photon": "Photon (Für bildlastige PDFs)", + "condenseInfo": "Condense nutzt fortschrittliche Komprimierung: entfernt unnötige Daten, optimiert Bilder, reduziert Schriftarten. Optimal für die meisten PDFs.", + "photonInfo": "Photon wandelt Seiten in Bilder um. Für bildlastige/gescannte PDFs.", + "photonWarning": "Warnung: Text wird nicht mehr auswählbar und Links funktionieren nicht mehr.", + "levelLabel": "Komprimierungsstufe", + "light": "Leicht (Qualität erhalten)", + "balanced": "Ausgewogen (Empfohlen)", + "aggressive": "Aggressiv (Kleinere Dateien)", + "extreme": "Extrem (Maximale Komprimierung)", + "grayscale": "In Graustufen umwandeln", + "grayscaleHint": "Reduziert Dateigröße durch Entfernen von Farbinformationen", + "customSettings": "Erweiterte Einstellungen", + "customSettingsHint": "Komprimierungsparameter anpassen:", + "outputQuality": "Ausgabequalität", + "resizeImagesTo": "Bilder anpassen auf", + "onlyProcessAbove": "Nur verarbeiten über", + "removeMetadata": "Metadaten entfernen", + "subsetFonts": "Schriftarten optimieren (ungenutzte Zeichen entfernen)", + "removeThumbnails": "Eingebettete Miniaturansichten entfernen", + "compressButton": "PDF komprimieren" + }, + "pdfEditor": { + "name": "PDF-Editor", + "subtitle": "Annotieren, hervorheben, schwärzen, kommentieren, Formen/Bilder hinzufügen, suchen und PDFs anzeigen." + }, + "jpgToPdf": { + "name": "JPG zu PDF", + "subtitle": "Eine PDF aus JPG, JPEG und JPEG2000 (JP2/JPX) Bildern erstellen." + }, + "signPdf": { + "name": "PDF unterschreiben", + "subtitle": "Zeichnen, tippen oder laden Sie Ihre Unterschrift hoch." + }, + "cropPdf": { + "name": "PDF zuschneiden", + "subtitle": "Die Ränder jeder Seite in Ihrer PDF beschneiden." + }, + "extractPages": { + "name": "Seiten extrahieren", + "subtitle": "Eine Auswahl von Seiten als neue Dateien speichern." + }, + "duplicateOrganize": { + "name": "Duplizieren & Organisieren", + "subtitle": "Seiten duplizieren, neu anordnen und löschen." + }, + "deletePages": { + "name": "Seiten löschen", + "subtitle": "Bestimmte Seiten aus Ihrem Dokument entfernen." + }, + "editBookmarks": { + "name": "Lesezeichen bearbeiten", + "subtitle": "PDF-Lesezeichen hinzufügen, bearbeiten, importieren, löschen und extrahieren." + }, + "tableOfContents": { + "name": "Inhaltsverzeichnis", + "subtitle": "Ein Inhaltsverzeichnis aus PDF-Lesezeichen generieren." + }, + "pageNumbers": { + "name": "Seitenzahlen", + "subtitle": "Seitenzahlen in Ihr Dokument einfügen." + }, + "addWatermark": { + "name": "Wasserzeichen hinzufügen", + "subtitle": "Text oder ein Bild über Ihre PDF-Seiten stempeln." + }, + "headerFooter": { + "name": "Kopf- & Fußzeile", + "subtitle": "Text oben und unten auf Seiten hinzufügen." + }, + "invertColors": { + "name": "Farben invertieren", + "subtitle": "Eine \"Dunkelmodus\"-Version Ihrer PDF erstellen." + }, + "backgroundColor": { + "name": "Hintergrundfarbe", + "subtitle": "Die Hintergrundfarbe Ihrer PDF ändern." + }, + "changeTextColor": { + "name": "Textfarbe ändern", + "subtitle": "Die Farbe des Textes in Ihrer PDF ändern." + }, + "addStamps": { + "name": "Stempel hinzufügen", + "subtitle": "Bildstempel zu Ihrer PDF über die Annotations-Symbolleiste hinzufügen.", + "usernameLabel": "Stempel-Benutzername", + "usernamePlaceholder": "Geben Sie Ihren Namen ein (für Stempel)", + "usernameHint": "Dieser Name erscheint auf von Ihnen erstellten Stempeln." + }, + "removeAnnotations": { + "name": "Annotationen entfernen", + "subtitle": "Kommentare, Hervorhebungen und Links entfernen." + }, + "pdfFormFiller": { + "name": "PDF-Formular ausfüllen", + "subtitle": "Formulare direkt im Browser ausfüllen. Unterstützt auch XFA-Formulare." + }, + "createPdfForm": { + "name": "PDF-Formular erstellen", + "subtitle": "Ausfüllbare PDF-Formulare mit Drag-and-Drop-Textfeldern erstellen." + }, + "removeBlankPages": { + "name": "Leere Seiten entfernen", + "subtitle": "Leere Seiten automatisch erkennen und löschen." + }, + "imageToPdf": { + "name": "Bilder zu PDF", + "subtitle": "JPG, PNG, BMP, GIF, TIFF, PNM, PGM, PBM, PPM, PAM, JXR, JPX, JP2, PSD, SVG, HEIC, WebP in PDF konvertieren." + }, + "pngToPdf": { + "name": "PNG zu PDF", + "subtitle": "Eine PDF aus einem oder mehreren PNG-Bildern erstellen." + }, + "webpToPdf": { + "name": "WebP zu PDF", + "subtitle": "Eine PDF aus einem oder mehreren WebP-Bildern erstellen." + }, + "svgToPdf": { + "name": "SVG zu PDF", + "subtitle": "Eine PDF aus einem oder mehreren SVG-Bildern erstellen." + }, + "bmpToPdf": { + "name": "BMP zu PDF", + "subtitle": "Eine PDF aus einem oder mehreren BMP-Bildern erstellen." + }, + "heicToPdf": { + "name": "HEIC zu PDF", + "subtitle": "Eine PDF aus einem oder mehreren HEIC-Bildern erstellen." + }, + "tiffToPdf": { + "name": "TIFF zu PDF", + "subtitle": "Eine PDF aus einem oder mehreren TIFF-Bildern erstellen." + }, + "textToPdf": { + "name": "Text zu PDF", + "subtitle": "Eine Textdatei in eine PDF konvertieren." + }, + "jsonToPdf": { + "name": "JSON zu PDF", + "subtitle": "JSON-Dateien in PDF-Format konvertieren." + }, + "pdfToJpg": { + "name": "PDF zu JPG", + "subtitle": "Jede PDF-Seite in ein JPG-Bild konvertieren." + }, + "pdfToPng": { + "name": "PDF zu PNG", + "subtitle": "Jede PDF-Seite in ein PNG-Bild konvertieren." + }, + "pdfToWebp": { + "name": "PDF zu WebP", + "subtitle": "Jede PDF-Seite in ein WebP-Bild konvertieren." + }, + "pdfToBmp": { + "name": "PDF zu BMP", + "subtitle": "Jede PDF-Seite in ein BMP-Bild konvertieren." + }, + "pdfToTiff": { + "name": "PDF zu TIFF", + "subtitle": "Jede PDF-Seite in ein TIFF-Bild konvertieren." + }, + "pdfToGreyscale": { + "name": "PDF zu Graustufen", + "subtitle": "Alle Farben in Schwarz-Weiß konvertieren." + }, + "pdfToJson": { + "name": "PDF zu JSON", + "subtitle": "PDF-Dateien in JSON-Format konvertieren." + }, + "ocrPdf": { + "name": "OCR PDF", + "subtitle": "Eine PDF durchsuchbar und kopierbar machen." + }, + "alternateMix": { + "name": "Seiten abwechselnd mischen", + "subtitle": "PDFs durch abwechselnde Seiten aus jedem PDF zusammenführen. Lesezeichen werden beibehalten." + }, + "addAttachments": { + "name": "Anhänge hinzufügen", + "subtitle": "Eine oder mehrere Dateien in Ihre PDF einbetten." + }, + "extractAttachments": { + "name": "Anhänge extrahieren", + "subtitle": "Alle eingebetteten Dateien aus PDF(s) als ZIP extrahieren." + }, + "editAttachments": { + "name": "Anhänge bearbeiten", + "subtitle": "Anhänge in Ihrer PDF anzeigen oder entfernen." + }, + "dividePages": { + "name": "Seiten teilen", + "subtitle": "Seiten horizontal oder vertikal teilen." + }, + "addBlankPage": { + "name": "Leere Seite hinzufügen", + "subtitle": "Eine leere Seite an beliebiger Stelle in Ihre PDF einfügen." + }, + "reversePages": { + "name": "Seiten umkehren", + "subtitle": "Die Reihenfolge aller Seiten in Ihrem Dokument umkehren." + }, + "rotatePdf": { + "name": "PDF drehen", + "subtitle": "Seiten in 90-Grad-Schritten drehen." + }, + "rotateCustom": { + "name": "Um benutzerdefinierte Grad drehen", + "subtitle": "Seiten um einen beliebigen Winkel drehen." + }, + "nUpPdf": { + "name": "N-Up PDF", + "subtitle": "Mehrere Seiten auf einem einzigen Blatt anordnen." + }, + "combineToSinglePage": { + "name": "Zu einer Seite kombinieren", + "subtitle": "Alle Seiten zu einem fortlaufenden Dokument zusammenfügen." + }, + "viewMetadata": { + "name": "Metadaten anzeigen", + "subtitle": "Die versteckten Eigenschaften Ihrer PDF inspizieren." + }, + "editMetadata": { + "name": "Metadaten bearbeiten", + "subtitle": "Autor, Titel und andere Eigenschaften ändern." + }, + "pdfsToZip": { + "name": "PDFs zu ZIP", + "subtitle": "Mehrere PDF-Dateien in ein ZIP-Archiv packen." + }, + "comparePdfs": { + "name": "PDFs vergleichen", + "subtitle": "Zwei PDFs nebeneinander vergleichen." + }, + "posterizePdf": { + "name": "PDF posterisieren", + "subtitle": "Eine große Seite in mehrere kleinere Seiten aufteilen." + }, + "fixPageSize": { + "name": "Seitengröße reparieren", + "subtitle": "Alle Seiten auf eine einheitliche Größe standardisieren." + }, + "linearizePdf": { + "name": "PDF linearisieren", + "subtitle": "PDF für schnelle Web-Anzeige optimieren." + }, + "pageDimensions": { + "name": "Seitenmaße", + "subtitle": "Seitengröße, Ausrichtung und Einheiten analysieren." + }, + "removeRestrictions": { + "name": "Beschränkungen entfernen", + "subtitle": "Passwortschutz und Sicherheitsbeschränkungen von digital signierten PDF-Dateien entfernen." + }, + "repairPdf": { + "name": "PDF reparieren", + "subtitle": "Daten aus beschädigten PDF-Dateien wiederherstellen." + }, + "encryptPdf": { + "name": "PDF verschlüsseln", + "subtitle": "Ihre PDF durch Hinzufügen eines Passworts sperren." + }, + "sanitizePdf": { + "name": "PDF bereinigen", + "subtitle": "Metadaten, Annotationen, Skripte und mehr entfernen." + }, + "decryptPdf": { + "name": "PDF entschlüsseln", + "subtitle": "PDF durch Entfernen des Passwortschutzes entsperren." + }, + "flattenPdf": { + "name": "PDF reduzieren", + "subtitle": "Formularfelder und Annotationen nicht editierbar machen." + }, + "removeMetadata": { + "name": "Metadaten entfernen", + "subtitle": "Versteckte Daten aus Ihrer PDF entfernen." + }, + "changePermissions": { + "name": "Berechtigungen ändern", + "subtitle": "Benutzerberechtigungen für eine PDF festlegen oder ändern." + }, + "odtToPdf": { + "name": "ODT zu PDF", + "subtitle": "OpenDocument Text-Dateien in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "ODT-Dateien", + "convertButton": "In PDF konvertieren" + }, + "csvToPdf": { + "name": "CSV zu PDF", + "subtitle": "CSV-Tabellendateien in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "CSV-Dateien", + "convertButton": "In PDF konvertieren" + }, + "rtfToPdf": { + "name": "RTF zu PDF", + "subtitle": "Rich Text Format-Dokumente in PDF konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "RTF-Dateien", + "convertButton": "In PDF konvertieren" + }, + "wordToPdf": { + "name": "Word zu PDF", + "subtitle": "Word-Dokumente (DOCX, DOC, ODT, RTF) in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "DOCX, DOC, ODT, RTF-Dateien", + "convertButton": "In PDF konvertieren" + }, + "excelToPdf": { + "name": "Excel zu PDF", + "subtitle": "Excel-Tabellen (XLSX, XLS, ODS, CSV) in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "XLSX, XLS, ODS, CSV-Dateien", + "convertButton": "In PDF konvertieren" + }, + "powerpointToPdf": { + "name": "PowerPoint zu PDF", + "subtitle": "PowerPoint-Präsentationen (PPTX, PPT, ODP) in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "PPTX, PPT, ODP-Dateien", + "convertButton": "In PDF konvertieren" + }, + "markdownToPdf": { + "name": "Markdown zu PDF", + "subtitle": "Schreiben oder fügen Sie Markdown ein und exportieren Sie es als schön formatiertes PDF.", + "paneMarkdown": "Markdown", + "panePreview": "Vorschau", + "btnUpload": "Hochladen", + "btnSyncScroll": "Sync-Scrollen", + "btnSettings": "Einstellungen", + "btnExportPdf": "PDF exportieren", + "settingsTitle": "Markdown-Einstellungen", + "settingsPreset": "Voreinstellung", + "presetDefault": "Standard (GFM-ähnlich)", + "presetCommonmark": "CommonMark (strikt)", + "presetZero": "Minimal (keine Funktionen)", + "settingsOptions": "Markdown-Optionen", + "optAllowHtml": "HTML-Tags erlauben", + "optBreaks": "Zeilenumbrüche in
umwandeln", + "optLinkify": "URLs automatisch in Links umwandeln", + "optTypographer": "Typograf (intelligente Anführungszeichen usw.)" + }, + "pdfBooklet": { + "name": "PDF-Broschüre", + "subtitle": "Seiten für beidseitigen Broschürendruck neu anordnen. Falten und heften zum Erstellen einer Broschüre.", + "howItWorks": "So funktioniert es:", + "step1": "Eine PDF-Datei hochladen.", + "step2": "Die Seiten werden in Broschürenreihenfolge neu angeordnet.", + "step3": "Beidseitig drucken, an der kurzen Kante wenden, falten und heften.", + "paperSize": "Papiergröße", + "orientation": "Ausrichtung", + "portrait": "Hochformat", + "landscape": "Querformat", + "pagesPerSheet": "Seiten pro Blatt", + "createBooklet": "Broschüre erstellen", + "processing": "Verarbeitung...", + "pageCount": "Die Seitenzahl wird bei Bedarf auf ein Vielfaches von 4 aufgerundet." + }, + "xpsToPdf": { + "name": "XPS zu PDF", + "subtitle": "XPS/OXPS-Dokumente in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "XPS, OXPS-Dateien", + "convertButton": "In PDF konvertieren" + }, + "mobiToPdf": { + "name": "MOBI zu PDF", + "subtitle": "MOBI-E-Books in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "MOBI-Dateien", + "convertButton": "In PDF konvertieren" + }, + "epubToPdf": { + "name": "EPUB zu PDF", + "subtitle": "EPUB-E-Books in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "EPUB-Dateien", + "convertButton": "In PDF konvertieren" + }, + "fb2ToPdf": { + "name": "FB2 zu PDF", + "subtitle": "FictionBook (FB2) E-Books in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "FB2-Dateien", + "convertButton": "In PDF konvertieren" + }, + "cbzToPdf": { + "name": "CBZ zu PDF", + "subtitle": "Comic-Archive (CBZ/CBR) in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "CBZ, CBR-Dateien", + "convertButton": "In PDF konvertieren" + }, + "wpdToPdf": { + "name": "WPD zu PDF", + "subtitle": "WordPerfect-Dokumente (WPD) in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "WPD-Dateien", + "convertButton": "In PDF konvertieren" + }, + "wpsToPdf": { + "name": "WPS zu PDF", + "subtitle": "WPS Office-Dokumente in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "WPS-Dateien", + "convertButton": "In PDF konvertieren" + }, + "xmlToPdf": { + "name": "XML zu PDF", + "subtitle": "XML-Dokumente in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "XML-Dateien", + "convertButton": "In PDF konvertieren" + }, + "pagesToPdf": { + "name": "Pages zu PDF", + "subtitle": "Apple Pages-Dokumente in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "Pages-Dateien", + "convertButton": "In PDF konvertieren" + }, + "odgToPdf": { + "name": "ODG zu PDF", + "subtitle": "OpenDocument Graphics (ODG) Dateien in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "ODG-Dateien", + "convertButton": "In PDF konvertieren" + }, + "odsToPdf": { + "name": "ODS zu PDF", + "subtitle": "OpenDocument Spreadsheet (ODS) Dateien in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "ODS-Dateien", + "convertButton": "In PDF konvertieren" + }, + "odpToPdf": { + "name": "ODP zu PDF", + "subtitle": "OpenDocument Presentation (ODP) Dateien in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "ODP-Dateien", + "convertButton": "In PDF konvertieren" + }, + "pubToPdf": { + "name": "PUB zu PDF", + "subtitle": "Microsoft Publisher (PUB) Dateien in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "PUB-Dateien", + "convertButton": "In PDF konvertieren" + }, + "vsdToPdf": { + "name": "VSD zu PDF", + "subtitle": "Microsoft Visio (VSD, VSDX) Dateien in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "VSD, VSDX-Dateien", + "convertButton": "In PDF konvertieren" + }, + "psdToPdf": { + "name": "PSD zu PDF", + "subtitle": "Adobe Photoshop (PSD) Dateien in PDF-Format konvertieren. Unterstützt mehrere Dateien.", + "acceptedFormats": "PSD-Dateien", + "convertButton": "In PDF konvertieren" + }, + "pdfToSvg": { + "name": "PDF zu SVG", + "subtitle": "Jede Seite einer PDF-Datei in eine skalierbare Vektorgrafik (SVG) konvertieren für perfekte Qualität in jeder Größe." + }, + "extractTables": { + "name": "PDF-Tabellen extrahieren", + "subtitle": "Tabellen aus PDF-Dateien extrahieren und als CSV, JSON oder Markdown exportieren." + }, + "pdfToCsv": { + "name": "PDF zu CSV", + "subtitle": "Tabellen aus PDF extrahieren und in CSV-Format konvertieren." + }, + "pdfToExcel": { + "name": "PDF zu Excel", + "subtitle": "Tabellen aus PDF extrahieren und in Excel (XLSX) Format konvertieren." + }, + "pdfToText": { + "name": "PDF zu Text", + "subtitle": "Text aus PDF-Dateien extrahieren und als Textdatei (.txt) speichern. Unterstützt mehrere Dateien.", + "note": "Dieses Tool funktioniert NUR mit digital erstellten PDFs. Für gescannte Dokumente oder bildbasierte PDFs verwenden Sie stattdessen unser OCR PDF-Tool.", + "convertButton": "Text extrahieren" + }, + "digitalSignPdf": { + "name": "Digitale PDF-Signatur", + "pageTitle": "Digitale PDF-Signatur - Kryptografische Signatur hinzufügen | BentoPDF", + "subtitle": "Fügen Sie eine kryptografische digitale Signatur mit X.509-Zertifikaten zu Ihrer PDF hinzu. Unterstützt PKCS#12 (.pfx, .p12) und PEM-Formate. Ihr privater Schlüssel verlässt niemals Ihren Browser.", + "certificateSection": "Zertifikat", + "uploadCert": "Zertifikat hochladen (.pfx, .p12)", + "certPassword": "Zertifikat-Passwort", + "certPasswordPlaceholder": "Zertifikat-Passwort eingeben", + "certInfo": "Zertifikat-Informationen", + "certSubject": "Betreff", + "certIssuer": "Aussteller", + "certValidity": "Gültig", + "signatureDetails": "Signatur-Details (Optional)", + "reason": "Grund", + "reasonPlaceholder": "z.B. Ich genehmige dieses Dokument", + "location": "Ort", + "locationPlaceholder": "z.B. Berlin, Deutschland", + "contactInfo": "Kontaktdaten", + "contactPlaceholder": "z.B. email@beispiel.de", + "applySignature": "Digitale Signatur anwenden", + "successMessage": "PDF erfolgreich signiert! Die Signatur kann in jedem PDF-Reader überprüft werden." + }, + "validateSignaturePdf": { + "name": "PDF-Signatur überprüfen", + "pageTitle": "PDF-Signatur überprüfen - Digitale Signaturen verifizieren | BentoPDF", + "subtitle": "Überprüfen Sie digitale Signaturen in Ihren PDF-Dateien. Prüfen Sie die Zertifikatsgültigkeit, sehen Sie Unterzeichnerdetails und bestätigen Sie die Dokumentenintegrität. Die gesamte Verarbeitung erfolgt in Ihrem Browser." + }, + "emailToPdf": { + "name": "E-Mail zu PDF", + "subtitle": "E-Mail-Dateien (EML, MSG) in PDF-Format konvertieren. Unterstützt Outlook-Exporte und Standard-E-Mail-Formate.", + "acceptedFormats": "EML, MSG-Dateien", + "convertButton": "In PDF konvertieren" + }, + "fontToOutline": { + "name": "Schriftart zu Umriss", + "subtitle": "Alle Schriftarten in Vektorumrisse für konsistente Darstellung auf allen Geräten konvertieren." + }, + "deskewPdf": { + "name": "PDF entzerren", + "subtitle": "Automatisch schiefe gescannte Seiten mit OpenCV begradigen." + } +} diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 2ffd41b..f130779 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -1,318 +1,323 @@ { - "nav": { - "home": "Home", - "about": "About", - "contact": "Contact", - "licensing": "Licensing", - "allTools": "All Tools", - "openMainMenu": "Open main menu", - "language": "Language" + "nav": { + "home": "Home", + "about": "About", + "contact": "Contact", + "licensing": "Licensing", + "allTools": "All Tools", + "openMainMenu": "Open main menu", + "language": "Language" + }, + "donation": { + "message": "Love BentoPDF? Help us keep it free and open source!", + "button": "Donate" + }, + "hero": { + "title": "The", + "pdfToolkit": "PDF Toolkit", + "builtForPrivacy": "built for privacy", + "noSignups": "No Signups", + "unlimitedUse": "Unlimited Use", + "worksOffline": "Works Offline", + "startUsing": "Start Using Now" + }, + "usedBy": { + "title": "Used by companies and people working at" + }, + "features": { + "title": "Why choose", + "bentoPdf": "BentoPDF?", + "noSignup": { + "title": "No Signup", + "description": "Start instantly, no accounts or emails." }, - "hero": { - "title": "The", - "pdfToolkit": "PDF Toolkit", - "builtForPrivacy": "built for privacy", - "noSignups": "No Signups", - "unlimitedUse": "Unlimited Use", - "worksOffline": "Works Offline", - "startUsing": "Start Using Now" + "noUploads": { + "title": "No Uploads", + "description": "100% client-side, your files never leave your device." }, - "usedBy": { - "title": "Used by companies and people working at" + "foreverFree": { + "title": "Forever Free", + "description": "All tools, no trials, no paywalls." }, - "features": { - "title": "Why choose", - "bentoPdf": "BentoPDF?", - "noSignup": { - "title": "No Signup", - "description": "Start instantly, no accounts or emails." - }, - "noUploads": { - "title": "No Uploads", - "description": "100% client-side, your files never leave your device." - }, - "foreverFree": { - "title": "Forever Free", - "description": "All tools, no trials, no paywalls." - }, - "noLimits": { - "title": "No Limits", - "description": "Use as much as you want, no hidden caps." - }, - "batchProcessing": { - "title": "Batch Processing", - "description": "Handle unlimited PDFs in one go." - }, - "lightningFast": { - "title": "Lightning Fast", - "description": "Process PDFs instantly, without waiting or delays." - } + "noLimits": { + "title": "No Limits", + "description": "Use as much as you want, no hidden caps." }, - "tools": { - "title": "Get Started with", - "toolsLabel": "Tools", - "subtitle": "Click a tool to open the file uploader", - "searchPlaceholder": "Search for a tool (e.g., 'split', 'organize'...)", - "backToTools": "Back to Tools" + "batchProcessing": { + "title": "Batch Processing", + "description": "Handle unlimited PDFs in one go." }, - "upload": { - "clickToSelect": "Click to select a file", - "orDragAndDrop": "or drag and drop", - "pdfOrImages": "PDFs or Images", - "filesNeverLeave": "Your files never leave your device.", - "addMore": "Add More Files", - "clearAll": "Clear All" - }, - "loader": { - "processing": "Processing..." - }, - "alert": { - "title": "Alert", - "ok": "OK" - }, - "preview": { - "title": "Document Preview", - "downloadAsPdf": "Download as PDF", - "close": "Close" - }, - "settings": { - "title": "Settings", - "shortcuts": "Shortcuts", - "preferences": "Preferences", - "displayPreferences": "Display Preferences", - "searchShortcuts": "Search shortcuts...", - "shortcutsInfo": "Press and hold keys to set a shortcut. Changes are auto-saved.", - "shortcutsWarning": "⚠️ Avoid common browser shortcuts (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N etc.) as they may not work reliably.", - "import": "Import", - "export": "Export", - "resetToDefaults": "Reset to Defaults", - "fullWidthMode": "Full Width Mode", - "fullWidthDescription": "Use the full screen width for all tools instead of a centered container", - "settingsAutoSaved": "Settings are automatically saved", - "clickToSet": "Click to set", - "pressKeys": "Press keys...", - "warnings": { - "alreadyInUse": "Shortcut Already in Use", - "assignedTo": "is already assigned to:", - "chooseDifferent": "Please choose a different shortcut.", - "reserved": "Reserved Shortcut Warning", - "commonlyUsed": "is commonly used for:", - "unreliable": "This shortcut may not work reliably or might conflict with browser/system behavior.", - "useAnyway": "Do you want to use it anyway?", - "resetTitle": "Reset Shortcuts", - "resetMessage": "Are you sure you want to reset all shortcuts to default?

This action cannot be undone.", - "importSuccessTitle": "Import Successful", - "importSuccessMessage": "Shortcuts imported successfully!", - "importFailTitle": "Import Failed", - "importFailMessage": "Failed to import shortcuts. Invalid file format." - } - }, - "warning": { - "title": "Warning", - "cancel": "Cancel", - "proceed": "Proceed" - }, - "compliance": { - "title": "Your data never leaves your device", - "weKeep": "We keep", - "yourInfoSafe": "your information safe", - "byFollowingStandards": "by following global security standards.", - "processingLocal": "All the processing happens locally on your device.", - "gdpr": { - "title": "GDPR compliance", - "description": "Protects the personal data and privacy of individuals within the European Union." - }, - "ccpa": { - "title": "CCPA compliance", - "description": "Gives California residents rights over how their personal information is collected, used, and shared." - }, - "hipaa": { - "title": "HIPAA compliance", - "description": "Sets safeguards for handling sensitive health information in the United States healthcare system." - } - }, - "faq": { - "title": "Frequently Asked", - "questions": "Questions", - "isFree": { - "question": "Is BentoPDF really free?", - "answer": "Yes, absolutely. All tools on BentoPDF are 100% free to use, with no file limits, no sign-ups, and no watermarks. We believe everyone deserves access to simple, powerful PDF tools without a paywall." - }, - "areFilesSecure": { - "question": "Are my files secure? Where are they processed?", - "answer": "Your files are as secure as possible because they never leave your computer. All processing happens directly in your web browser (client-side). We never upload your files to a server, so you maintain complete privacy and control over your documents." - }, - "platforms": { - "question": "Does it work on Mac, Windows, and Mobile?", - "answer": "Yes! Since BentoPDF runs entirely in your browser, it works on any operating system with a modern web browser, including Windows, macOS, Linux, iOS, and Android." - }, - "gdprCompliant": { - "question": "Is BentoPDF GDPR compliant?", - "answer": "Yes. BentoPDF is fully GDPR compliant. Since all file processing happens locally in your browser and we never collect or transmit your files to any server, we have no access to your data. This ensures you are always in control of your documents." - }, - "dataStorage": { - "question": "Do you store or track any of my files?", - "answer": "No. We never store, track, or log your files. Everything you do on BentoPDF happens in your browser memory and disappears once you close the page. There are no uploads, no history logs, and no servers involved." - }, - "different": { - "question": "What makes BentoPDF different from other PDF tools?", - "answer": "Most PDF tools upload your files to a server for processing. BentoPDF never does that. We use secure, modern web technology to process your files directly in your browser. This means faster performance, stronger privacy, and complete peace of mind." - }, - "browserBased": { - "question": "How does browser-based processing keep me safe?", - "answer": "By running entirely inside your browser, BentoPDF ensures that your files never leave your device. This eliminates the risks of server hacks, data breaches, or unauthorized access. Your files remain yours—always." - }, - "analytics": { - "question": "Do you use cookies or analytics to track me?", - "answer": "We care about your privacy. BentoPDF does not track personal information. We use Simple Analytics solely to see anonymous visit counts. This means we can know how many users visit our site, but we never know who you are. Simple Analytics is fully GDPR-compliant and respects your privacy." - } - }, - "testimonials": { - "title": "What Our", - "users": "Users", - "say": "Say" - }, - "support": { - "title": "Like My Work?", - "description": "BentoPDF is a passion project, built to provide a free, private, and powerful PDF toolkit for everyone. If you find it useful, consider supporting its development. Every coffee helps!", - "buyMeCoffee": "Buy Me a Coffee" - }, - "footer": { - "copyright": "© 2025 BentoPDF. All rights reserved.", - "version": "Version", - "company": "Company", - "aboutUs": "About Us", - "faqLink": "FAQ", - "contactUs": "Contact Us", - "legal": "Legal", - "termsAndConditions": "Terms and Conditions", - "privacyPolicy": "Privacy Policy", - "followUs": "Follow Us" - }, - "merge": { - "title": "Merge PDFs", - "description": "Combine whole files, or select specific pages to merge into a new document.", - "fileMode": "File Mode", - "pageMode": "Page Mode", - "howItWorks": "How it works:", - "fileModeInstructions": [ - "Click and drag the icon to change the order of the files.", - "In the \"Pages\" box for each file, you can specify ranges (e.g., \"1-3, 5\") to merge only those pages.", - "Leave the \"Pages\" box blank to include all pages from that file." - ], - "pageModeInstructions": [ - "All pages from your uploaded PDFs are shown below.", - "Simply drag and drop the individual page thumbnails to create the exact order you want for your new file." - ], - "mergePdfs": "Merge PDFs" - }, - "common": { - "page": "Page", - "pages": "Pages", - "of": "of", - "download": "Download", - "cancel": "Cancel", - "save": "Save", - "delete": "Delete", - "edit": "Edit", - "add": "Add", - "remove": "Remove", - "loading": "Loading...", - "error": "Error", - "success": "Success", - "file": "File", - "files": "Files" - }, - "about": { - "hero": { - "title": "We believe PDF tools should be", - "subtitle": "fast, private, and free.", - "noCompromises": "No compromises." - }, - "mission": { - "title": "Our Mission", - "description": "To provide the most comprehensive PDF toolbox that respects your privacy and never asks for payment. We believe essential document tools should be accessible to everyone, everywhere, without barriers." - }, - "philosophy": { - "label": "Our Core Philosophy", - "title": "Privacy First. Always.", - "description": "In an era where data is a commodity, we take a different approach. All processing for Bentopdf tools happens locally in your browser. This means your files never touch our servers, we never see your documents, and we don't track what you do. Your documents remain completely and unequivocally private. It's not just a feature; it's our foundation." - }, - "whyBentopdf": { - "title": "Why", - "speed": { - "title": "Built for Speed", - "description": "No waiting for uploads or downloads to a server. By processing files directly in your browser using modern web technologies like WebAssembly, we offer unparalleled speed for all our tools." - }, - "free": { - "title": "Completely Free", - "description": "No trials, no subscriptions, no hidden fees, and no \"premium\" features held hostage. We believe powerful PDF tools should be a public utility, not a profit center." - }, - "noAccount": { - "title": "No Account Required", - "description": "Start using any tool immediately. We don't need your email, a password, or any personal information. Your workflow should be frictionless and anonymous." - }, - "openSource": { - "title": "Open Source Spirit", - "description": "Built with transparency in mind. We leverage incredible open-source libraries like PDF-lib and PDF.js, and believe in the community-driven effort to make powerful tools accessible to everyone." - } - }, - "cta": { - "title": "Ready to get started?", - "description": "Join thousands of users who trust Bentopdf for their daily document needs. Experience the difference that privacy and performance can make.", - "button": "Explore All Tools" - } - }, - "contact": { - "title": "Get in Touch", - "subtitle": "We'd love to hear from you. Whether you have a question, feedback, or a feature request, please don't hesitate to reach out.", - "email": "You can reach us directly by email at:" - }, - "licensing": { - "title": "Licensing for", - "subtitle": "Choose the license that fits your needs." - }, - "multiTool": { - "uploadPdfs": "Upload PDFs", - "upload": "Upload", - "addBlankPage": "Add Blank Page", - "edit": "Edit:", - "undo": "Undo", - "redo": "Redo", - "reset": "Reset", - "selection": "Selection:", - "selectAll": "Select All", - "deselectAll": "Deselect All", - "rotate": "Rotate:", - "rotateLeft": "Left", - "rotateRight": "Right", - "transform": "Transform:", - "duplicate": "Duplicate", - "split": "Split", - "clear": "Clear:", - "delete": "Delete", - "download": "Download:", - "downloadSelected": "Download Selected", - "exportPdf": "Export PDF", - "uploadPdfFiles": "Select PDF Files", - "dragAndDrop": "Drag and drop PDF files here, or click to select", - "selectFiles": "Select Files", - "renderingPages": "Rendering pages...", - "actions": { - "duplicatePage": "Duplicate this page", - "deletePage": "Delete this page", - "insertPdf": "Insert PDF after this page", - "toggleSplit": "Toggle split after this page" - }, - "pleaseWait": "Please Wait", - "pagesRendering": "Pages are still being rendered. Please wait...", - "noPagesSelected": "No Pages Selected", - "selectOnePage": "Please select at least one page to download.", - "noPages": "No Pages", - "noPagesToExport": "There are no pages to export.", - "renderingTitle": "Rendering page previews", - "errorRendering": "Failed to render page thumbnails", - "error": "Error", - "failedToLoad": "Failed to load" + "lightningFast": { + "title": "Lightning Fast", + "description": "Process PDFs instantly, without waiting or delays." } -} \ No newline at end of file + }, + "tools": { + "title": "Get Started with", + "toolsLabel": "Tools", + "subtitle": "Click a tool to open the file uploader", + "searchPlaceholder": "Search for a tool (e.g., 'split', 'organize'...)", + "backToTools": "Back to Tools", + "firstLoadNotice": "First load takes a moment as we download our conversion engine. After that, all loads will be instant." + }, + "upload": { + "clickToSelect": "Click to select a file", + "orDragAndDrop": "or drag and drop", + "pdfOrImages": "PDFs or Images", + "filesNeverLeave": "Your files never leave your device.", + "addMore": "Add More Files", + "clearAll": "Clear All" + }, + "loader": { + "processing": "Processing..." + }, + "alert": { + "title": "Alert", + "ok": "OK" + }, + "preview": { + "title": "Document Preview", + "downloadAsPdf": "Download as PDF", + "close": "Close" + }, + "settings": { + "title": "Settings", + "shortcuts": "Shortcuts", + "preferences": "Preferences", + "displayPreferences": "Display Preferences", + "searchShortcuts": "Search shortcuts...", + "shortcutsInfo": "Press and hold keys to set a shortcut. Changes are auto-saved.", + "shortcutsWarning": "⚠️ Avoid common browser shortcuts (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N etc.) as they may not work reliably.", + "import": "Import", + "export": "Export", + "resetToDefaults": "Reset to Defaults", + "fullWidthMode": "Full Width Mode", + "fullWidthDescription": "Use the full screen width for all tools instead of a centered container", + "settingsAutoSaved": "Settings are automatically saved", + "clickToSet": "Click to set", + "pressKeys": "Press keys...", + "warnings": { + "alreadyInUse": "Shortcut Already in Use", + "assignedTo": "is already assigned to:", + "chooseDifferent": "Please choose a different shortcut.", + "reserved": "Reserved Shortcut Warning", + "commonlyUsed": "is commonly used for:", + "unreliable": "This shortcut may not work reliably or might conflict with browser/system behavior.", + "useAnyway": "Do you want to use it anyway?", + "resetTitle": "Reset Shortcuts", + "resetMessage": "Are you sure you want to reset all shortcuts to default?

This action cannot be undone.", + "importSuccessTitle": "Import Successful", + "importSuccessMessage": "Shortcuts imported successfully!", + "importFailTitle": "Import Failed", + "importFailMessage": "Failed to import shortcuts. Invalid file format." + } + }, + "warning": { + "title": "Warning", + "cancel": "Cancel", + "proceed": "Proceed" + }, + "compliance": { + "title": "Your data never leaves your device", + "weKeep": "We keep", + "yourInfoSafe": "your information safe", + "byFollowingStandards": "by following global security standards.", + "processingLocal": "All the processing happens locally on your device.", + "gdpr": { + "title": "GDPR compliance", + "description": "Protects the personal data and privacy of individuals within the European Union." + }, + "ccpa": { + "title": "CCPA compliance", + "description": "Gives California residents rights over how their personal information is collected, used, and shared." + }, + "hipaa": { + "title": "HIPAA compliance", + "description": "Sets safeguards for handling sensitive health information in the United States healthcare system." + } + }, + "faq": { + "title": "Frequently Asked", + "questions": "Questions", + "isFree": { + "question": "Is BentoPDF really free?", + "answer": "Yes, absolutely. All tools on BentoPDF are 100% free to use, with no file limits, no sign-ups, and no watermarks. We believe everyone deserves access to simple, powerful PDF tools without a paywall." + }, + "areFilesSecure": { + "question": "Are my files secure? Where are they processed?", + "answer": "Your files are as secure as possible because they never leave your computer. All processing happens directly in your web browser (client-side). We never upload your files to a server, so you maintain complete privacy and control over your documents." + }, + "platforms": { + "question": "Does it work on Mac, Windows, and Mobile?", + "answer": "Yes! Since BentoPDF runs entirely in your browser, it works on any operating system with a modern web browser, including Windows, macOS, Linux, iOS, and Android." + }, + "gdprCompliant": { + "question": "Is BentoPDF GDPR compliant?", + "answer": "Yes. BentoPDF is fully GDPR compliant. Since all file processing happens locally in your browser and we never collect or transmit your files to any server, we have no access to your data. This ensures you are always in control of your documents." + }, + "dataStorage": { + "question": "Do you store or track any of my files?", + "answer": "No. We never store, track, or log your files. Everything you do on BentoPDF happens in your browser memory and disappears once you close the page. There are no uploads, no history logs, and no servers involved." + }, + "different": { + "question": "What makes BentoPDF different from other PDF tools?", + "answer": "Most PDF tools upload your files to a server for processing. BentoPDF never does that. We use secure, modern web technology to process your files directly in your browser. This means faster performance, stronger privacy, and complete peace of mind." + }, + "browserBased": { + "question": "How does browser-based processing keep me safe?", + "answer": "By running entirely inside your browser, BentoPDF ensures that your files never leave your device. This eliminates the risks of server hacks, data breaches, or unauthorized access. Your files remain yours—always." + }, + "analytics": { + "question": "Do you use cookies or analytics to track me?", + "answer": "We care about your privacy. BentoPDF does not track personal information. We use Simple Analytics solely to see anonymous visit counts. This means we can know how many users visit our site, but we never know who you are. Simple Analytics is fully GDPR-compliant and respects your privacy." + } + }, + "testimonials": { + "title": "What Our", + "users": "Users", + "say": "Say" + }, + "support": { + "title": "Like My Work?", + "description": "BentoPDF is a passion project, built to provide a free, private, and powerful PDF toolkit for everyone. If you find it useful, consider supporting its development. Every coffee helps!", + "buyMeCoffee": "Buy Me a Coffee" + }, + "footer": { + "copyright": "© 2026 BentoPDF. All rights reserved.", + "version": "Version", + "company": "Company", + "aboutUs": "About Us", + "faqLink": "FAQ", + "contactUs": "Contact Us", + "legal": "Legal", + "termsAndConditions": "Terms and Conditions", + "privacyPolicy": "Privacy Policy", + "followUs": "Follow Us" + }, + "merge": { + "title": "Merge PDFs", + "description": "Combine whole files, or select specific pages to merge into a new document.", + "fileMode": "File Mode", + "pageMode": "Page Mode", + "howItWorks": "How it works:", + "fileModeInstructions": [ + "Click and drag the icon to change the order of the files.", + "In the \"Pages\" box for each file, you can specify ranges (e.g., \"1-3, 5\") to merge only those pages.", + "Leave the \"Pages\" box blank to include all pages from that file." + ], + "pageModeInstructions": [ + "All pages from your uploaded PDFs are shown below.", + "Simply drag and drop the individual page thumbnails to create the exact order you want for your new file." + ], + "mergePdfs": "Merge PDFs" + }, + "common": { + "page": "Page", + "pages": "Pages", + "of": "of", + "download": "Download", + "cancel": "Cancel", + "save": "Save", + "delete": "Delete", + "edit": "Edit", + "add": "Add", + "remove": "Remove", + "loading": "Loading...", + "error": "Error", + "success": "Success", + "file": "File", + "files": "Files" + }, + "about": { + "hero": { + "title": "We believe PDF tools should be", + "subtitle": "fast, private, and free.", + "noCompromises": "No compromises." + }, + "mission": { + "title": "Our Mission", + "description": "To provide the most comprehensive PDF toolbox that respects your privacy and never asks for payment. We believe essential document tools should be accessible to everyone, everywhere, without barriers." + }, + "philosophy": { + "label": "Our Core Philosophy", + "title": "Privacy First. Always.", + "description": "In an era where data is a commodity, we take a different approach. All processing for Bentopdf tools happens locally in your browser. This means your files never touch our servers, we never see your documents, and we don't track what you do. Your documents remain completely and unequivocally private. It's not just a feature; it's our foundation." + }, + "whyBentopdf": { + "title": "Why", + "speed": { + "title": "Built for Speed", + "description": "No waiting for uploads or downloads to a server. By processing files directly in your browser using modern web technologies like WebAssembly, we offer unparalleled speed for all our tools." + }, + "free": { + "title": "Completely Free", + "description": "No trials, no subscriptions, no hidden fees, and no \"premium\" features held hostage. We believe powerful PDF tools should be a public utility, not a profit center." + }, + "noAccount": { + "title": "No Account Required", + "description": "Start using any tool immediately. We don't need your email, a password, or any personal information. Your workflow should be frictionless and anonymous." + }, + "openSource": { + "title": "Open Source Spirit", + "description": "Built with transparency in mind. We leverage incredible open-source libraries like PDF-lib and PDF.js, and believe in the community-driven effort to make powerful tools accessible to everyone." + } + }, + "cta": { + "title": "Ready to get started?", + "description": "Join thousands of users who trust Bentopdf for their daily document needs. Experience the difference that privacy and performance can make.", + "button": "Explore All Tools" + } + }, + "contact": { + "title": "Get in Touch", + "subtitle": "We'd love to hear from you. Whether you have a question, feedback, or a feature request, please don't hesitate to reach out.", + "email": "You can reach us directly by email at:" + }, + "licensing": { + "title": "Licensing for", + "subtitle": "Choose the license that fits your needs." + }, + "multiTool": { + "uploadPdfs": "Upload PDFs", + "upload": "Upload", + "addBlankPage": "Add Blank Page", + "edit": "Edit:", + "undo": "Undo", + "redo": "Redo", + "reset": "Reset", + "selection": "Selection:", + "selectAll": "Select All", + "deselectAll": "Deselect All", + "rotate": "Rotate:", + "rotateLeft": "Left", + "rotateRight": "Right", + "transform": "Transform:", + "duplicate": "Duplicate", + "split": "Split", + "clear": "Clear:", + "delete": "Delete", + "download": "Download:", + "downloadSelected": "Download Selected", + "exportPdf": "Export PDF", + "uploadPdfFiles": "Select PDF Files", + "dragAndDrop": "Drag and drop PDF files here, or click to select", + "selectFiles": "Select Files", + "renderingPages": "Rendering pages...", + "actions": { + "duplicatePage": "Duplicate this page", + "deletePage": "Delete this page", + "insertPdf": "Insert PDF after this page", + "toggleSplit": "Toggle split after this page" + }, + "pleaseWait": "Please Wait", + "pagesRendering": "Pages are still being rendered. Please wait...", + "noPagesSelected": "No Pages Selected", + "selectOnePage": "Please select at least one page to download.", + "noPages": "No Pages", + "noPagesToExport": "There are no pages to export.", + "renderingTitle": "Rendering page previews", + "errorRendering": "Failed to render page thumbnails", + "error": "Error", + "failedToLoad": "Failed to load" + } +} diff --git a/public/locales/en/tools.json b/public/locales/en/tools.json index 3ebe684..e093480 100644 --- a/public/locales/en/tools.json +++ b/public/locales/en/tools.json @@ -1,282 +1,533 @@ { - "categories": { - "popularTools": "Popular Tools", - "editAnnotate": "Edit & Annotate", - "convertToPdf": "Convert to PDF", - "convertFromPdf": "Convert from PDF", - "organizeManage": "Organize & Manage", - "optimizeRepair": "Optimize & Repair", - "securePdf": "Secure PDF" - }, - "pdfMultiTool": { - "name": "PDF Multi Tool", - "subtitle": "Merge, Split, Organize, Delete, Rotate, Add Blank Pages, Extract and Duplicate in an unified interface." - }, - "mergePdf": { - "name": "Merge PDF", - "subtitle": "Combine multiple PDFs into one file. Preserves Bookmarks." - }, - "splitPdf": { - "name": "Split PDF", - "subtitle": "Extract a range of pages into a new PDF." - }, - "compressPdf": { - "name": "Compress PDF", - "subtitle": "Reduce the file size of your PDF." - }, - "pdfEditor": { - "name": "PDF Editor", - "subtitle": "Annotate, highlight, redact, comment, add shapes/images, search, and view PDFs." - }, - "jpgToPdf": { - "name": "JPG to PDF", - "subtitle": "Create a PDF from one or more JPG images." - }, - "signPdf": { - "name": "Sign PDF", - "subtitle": "Draw, type, or upload your signature." - }, - "cropPdf": { - "name": "Crop PDF", - "subtitle": "Trim the margins of every page in your PDF." - }, - "extractPages": { - "name": "Extract Pages", - "subtitle": "Save a selection of pages as new files." - }, - "duplicateOrganize": { - "name": "Duplicate & Organize", - "subtitle": "Duplicate, reorder, and delete pages." - }, - "deletePages": { - "name": "Delete Pages", - "subtitle": "Remove specific pages from your document." - }, - "editBookmarks": { - "name": "Edit Bookmarks", - "subtitle": "Add, edit, import, delete and extract PDF bookmarks." - }, - "tableOfContents": { - "name": "Table of Contents", - "subtitle": "Generate a table of contents page from PDF bookmarks." - }, - "pageNumbers": { - "name": "Page Numbers", - "subtitle": "Insert page numbers into your document." - }, - "addWatermark": { - "name": "Add Watermark", - "subtitle": "Stamp text or an image over your PDF pages." - }, - "headerFooter": { - "name": "Header & Footer", - "subtitle": "Add text to the top and bottom of pages." - }, - "invertColors": { - "name": "Invert Colors", - "subtitle": "Create a \"dark mode\" version of your PDF." - }, - "backgroundColor": { - "name": "Background Color", - "subtitle": "Change the background color of your PDF." - }, - "changeTextColor": { - "name": "Change Text Color", - "subtitle": "Change the color of text in your PDF." - }, - "addStamps": { - "name": "Add Stamps", - "subtitle": "Add image stamps to your PDF using the annotation toolbar.", - "usernameLabel": "Stamp Username", - "usernamePlaceholder": "Enter your name (for stamps)", - "usernameHint": "This name will appear on stamps you create." - }, - "removeAnnotations": { - "name": "Remove Annotations", - "subtitle": "Strip comments, highlights, and links." - }, - "pdfFormFiller": { - "name": "PDF Form Filler", - "subtitle": "Fill in forms directly in the browser. Also supports XFA forms." - }, - "createPdfForm": { - "name": "Create PDF Form", - "subtitle": "Create fillable PDF forms with drag-and-drop text fields." - }, - "removeBlankPages": { - "name": "Remove Blank Pages", - "subtitle": "Automatically detect and delete blank pages." - }, - "imageToPdf": { - "name": "Image to PDF", - "subtitle": "Convert JPG, PNG, WebP, BMP, TIFF, SVG, HEIC to PDF." - }, - "pngToPdf": { - "name": "PNG to PDF", - "subtitle": "Create a PDF from one or more PNG images." - }, - "webpToPdf": { - "name": "WebP to PDF", - "subtitle": "Create a PDF from one or more WebP images." - }, - "svgToPdf": { - "name": "SVG to PDF", - "subtitle": "Create a PDF from one or more SVG images." - }, - "bmpToPdf": { - "name": "BMP to PDF", - "subtitle": "Create a PDF from one or more BMP images." - }, - "heicToPdf": { - "name": "HEIC to PDF", - "subtitle": "Create a PDF from one or more HEIC images." - }, - "tiffToPdf": { - "name": "TIFF to PDF", - "subtitle": "Create a PDF from one or more TIFF images." - }, - "textToPdf": { - "name": "Text to PDF", - "subtitle": "Convert a plain text file into a PDF." - }, - "jsonToPdf": { - "name": "JSON to PDF", - "subtitle": "Convert JSON files to PDF format." - }, - "pdfToJpg": { - "name": "PDF to JPG", - "subtitle": "Convert each PDF page into a JPG image." - }, - "pdfToPng": { - "name": "PDF to PNG", - "subtitle": "Convert each PDF page into a PNG image." - }, - "pdfToWebp": { - "name": "PDF to WebP", - "subtitle": "Convert each PDF page into a WebP image." - }, - "pdfToBmp": { - "name": "PDF to BMP", - "subtitle": "Convert each PDF page into a BMP image." - }, - "pdfToTiff": { - "name": "PDF to TIFF", - "subtitle": "Convert each PDF page into a TIFF image." - }, - "pdfToGreyscale": { - "name": "PDF to Greyscale", - "subtitle": "Convert all colors to black and white." - }, - "pdfToJson": { - "name": "PDF to JSON", - "subtitle": "Convert PDF files to JSON format." - }, - "ocrPdf": { - "name": "OCR PDF", - "subtitle": "Make a PDF searchable and copyable." - }, - "alternateMix": { - "name": "Alternate & Mix Pages", - "subtitle": "Merge PDFs by alternating pages from each PDF. Preserves Bookmarks." - }, - "addAttachments": { - "name": "Add Attachments", - "subtitle": "Embed one or more files into your PDF." - }, - "extractAttachments": { - "name": "Extract Attachments", - "subtitle": "Extract all embedded files from PDF(s) as a ZIP." - }, - "editAttachments": { - "name": "Edit Attachments", - "subtitle": "View or remove attachments in your PDF." - }, - "dividePages": { - "name": "Divide Pages", - "subtitle": "Divide pages horizontally or vertically." - }, - "addBlankPage": { - "name": "Add Blank Page", - "subtitle": "Insert an empty page anywhere in your PDF." - }, - "reversePages": { - "name": "Reverse Pages", - "subtitle": "Flip the order of all pages in your document." - }, - "rotatePdf": { - "name": "Rotate PDF", - "subtitle": "Turn pages in 90-degree increments." - }, - "nUpPdf": { - "name": "N-Up PDF", - "subtitle": "Arrange multiple pages onto a single sheet." - }, - "combineToSinglePage": { - "name": "Combine to Single Page", - "subtitle": "Stitch all pages into one continuous scroll." - }, - "viewMetadata": { - "name": "View Metadata", - "subtitle": "Inspect the hidden properties of your PDF." - }, - "editMetadata": { - "name": "Edit Metadata", - "subtitle": "Change the author, title, and other properties." - }, - "pdfsToZip": { - "name": "PDFs to ZIP", - "subtitle": "Package multiple PDF files into a ZIP archive." - }, - "comparePdfs": { - "name": "Compare PDFs", - "subtitle": "Compare two PDFs side by side." - }, - "posterizePdf": { - "name": "Posterize PDF", - "subtitle": "Split a large page into multiple smaller pages." - }, - "fixPageSize": { - "name": "Fix Page Size", - "subtitle": "Standardize all pages to a uniform size." - }, - "linearizePdf": { - "name": "Linearize PDF", - "subtitle": "Optimize PDF for fast web viewing." - }, - "pageDimensions": { - "name": "Page Dimensions", - "subtitle": "Analyze page size, orientation, and units." - }, - "removeRestrictions": { - "name": "Remove Restrictions", - "subtitle": "Remove password protection and security restrictions associated with digitally signed PDF files." - }, - "repairPdf": { - "name": "Repair PDF", - "subtitle": "Recover data from corrupted or damaged PDF files." - }, - "encryptPdf": { - "name": "Encrypt PDF", - "subtitle": "Lock your PDF by adding a password." - }, - "sanitizePdf": { - "name": "Sanitize PDF", - "subtitle": "Remove metadata, annotations, scripts, and more." - }, - "decryptPdf": { - "name": "Decrypt PDF", - "subtitle": "Unlock PDF by removing password protection." - }, - "flattenPdf": { - "name": "Flatten PDF", - "subtitle": "Make form fields and annotations non-editable." - }, - "removeMetadata": { - "name": "Remove Metadata", - "subtitle": "Strip hidden data from your PDF." - }, - "changePermissions": { - "name": "Change Permissions", - "subtitle": "Set or change user permissions on a PDF." - } -} \ No newline at end of file + "categories": { + "popularTools": "Popular Tools", + "editAnnotate": "Edit & Annotate", + "convertToPdf": "Convert to PDF", + "convertFromPdf": "Convert from PDF", + "organizeManage": "Organize & Manage", + "optimizeRepair": "Optimize & Repair", + "securePdf": "Secure PDF" + }, + "pdfMultiTool": { + "name": "PDF Multi Tool", + "subtitle": "Merge, Split, Organize, Delete, Rotate, Add Blank Pages, Extract and Duplicate in an unified interface." + }, + "mergePdf": { + "name": "Merge PDF", + "subtitle": "Combine multiple PDFs into one file. Preserves Bookmarks." + }, + "splitPdf": { + "name": "Split PDF", + "subtitle": "Extract a range of pages into a new PDF." + }, + "compressPdf": { + "name": "Compress PDF", + "subtitle": "Reduce the file size of your PDF.", + "algorithmLabel": "Compression Algorithm", + "condense": "Condense (Recommended)", + "photon": "Photon (For Photo-Heavy PDFs)", + "condenseInfo": "Condense uses advanced compression: removes dead-weight, optimizes images, subsets fonts. Best for most PDFs.", + "photonInfo": "Photon converts pages to images. Use for photo-heavy/scanned PDFs.", + "photonWarning": "Warning: Text will become non-selectable and links will stop working.", + "levelLabel": "Compression Level", + "light": "Light (Preserve Quality)", + "balanced": "Balanced (Recommended)", + "aggressive": "Aggressive (Smaller Files)", + "extreme": "Extreme (Maximum Compression)", + "grayscale": "Convert to Grayscale", + "grayscaleHint": "Reduces file size by removing color information", + "customSettings": "Custom Settings", + "customSettingsHint": "Fine-tune compression parameters:", + "outputQuality": "Output Quality", + "resizeImagesTo": "Resize Images To", + "onlyProcessAbove": "Only Process Above", + "removeMetadata": "Remove metadata", + "subsetFonts": "Subset fonts (remove unused glyphs)", + "removeThumbnails": "Remove embedded thumbnails", + "compressButton": "Compress PDF" + }, + "pdfEditor": { + "name": "PDF Editor", + "subtitle": "Annotate, highlight, redact, comment, add shapes/images, search, and view PDFs." + }, + "jpgToPdf": { + "name": "JPG to PDF", + "subtitle": "Create a PDF from JPG, JPEG, and JPEG2000 (JP2/JPX) images." + }, + "signPdf": { + "name": "Sign PDF", + "subtitle": "Draw, type, or upload your signature." + }, + "cropPdf": { + "name": "Crop PDF", + "subtitle": "Trim the margins of every page in your PDF." + }, + "extractPages": { + "name": "Extract Pages", + "subtitle": "Save a selection of pages as new files." + }, + "duplicateOrganize": { + "name": "Duplicate & Organize", + "subtitle": "Duplicate, reorder, and delete pages." + }, + "deletePages": { + "name": "Delete Pages", + "subtitle": "Remove specific pages from your document." + }, + "editBookmarks": { + "name": "Edit Bookmarks", + "subtitle": "Add, edit, import, delete and extract PDF bookmarks." + }, + "tableOfContents": { + "name": "Table of Contents", + "subtitle": "Generate a table of contents page from PDF bookmarks." + }, + "pageNumbers": { + "name": "Page Numbers", + "subtitle": "Insert page numbers into your document." + }, + "addWatermark": { + "name": "Add Watermark", + "subtitle": "Stamp text or an image over your PDF pages." + }, + "headerFooter": { + "name": "Header & Footer", + "subtitle": "Add text to the top and bottom of pages." + }, + "invertColors": { + "name": "Invert Colors", + "subtitle": "Create a \"dark mode\" version of your PDF." + }, + "backgroundColor": { + "name": "Background Color", + "subtitle": "Change the background color of your PDF." + }, + "changeTextColor": { + "name": "Change Text Color", + "subtitle": "Change the color of text in your PDF." + }, + "addStamps": { + "name": "Add Stamps", + "subtitle": "Add image stamps to your PDF using the annotation toolbar.", + "usernameLabel": "Stamp Username", + "usernamePlaceholder": "Enter your name (for stamps)", + "usernameHint": "This name will appear on stamps you create." + }, + "removeAnnotations": { + "name": "Remove Annotations", + "subtitle": "Strip comments, highlights, and links." + }, + "pdfFormFiller": { + "name": "PDF Form Filler", + "subtitle": "Fill in forms directly in the browser. Also supports XFA forms." + }, + "createPdfForm": { + "name": "Create PDF Form", + "subtitle": "Create fillable PDF forms with drag-and-drop text fields." + }, + "removeBlankPages": { + "name": "Remove Blank Pages", + "subtitle": "Automatically detect and delete blank pages." + }, + "imageToPdf": { + "name": "Images to PDF", + "subtitle": "Convert JPG, PNG, BMP, GIF, TIFF, PNM, PGM, PBM, PPM, PAM, JXR, JPX, JP2, PSD, SVG, HEIC, WebP to PDF." + }, + "pngToPdf": { + "name": "PNG to PDF", + "subtitle": "Create a PDF from one or more PNG images." + }, + "webpToPdf": { + "name": "WebP to PDF", + "subtitle": "Create a PDF from one or more WebP images." + }, + "svgToPdf": { + "name": "SVG to PDF", + "subtitle": "Create a PDF from one or more SVG images." + }, + "bmpToPdf": { + "name": "BMP to PDF", + "subtitle": "Create a PDF from one or more BMP images." + }, + "heicToPdf": { + "name": "HEIC to PDF", + "subtitle": "Create a PDF from one or more HEIC images." + }, + "tiffToPdf": { + "name": "TIFF to PDF", + "subtitle": "Create a PDF from one or more TIFF images." + }, + "textToPdf": { + "name": "Text to PDF", + "subtitle": "Convert a plain text file into a PDF." + }, + "jsonToPdf": { + "name": "JSON to PDF", + "subtitle": "Convert JSON files to PDF format." + }, + "pdfToJpg": { + "name": "PDF to JPG", + "subtitle": "Convert each PDF page into a JPG image." + }, + "pdfToPng": { + "name": "PDF to PNG", + "subtitle": "Convert each PDF page into a PNG image." + }, + "pdfToWebp": { + "name": "PDF to WebP", + "subtitle": "Convert each PDF page into a WebP image." + }, + "pdfToBmp": { + "name": "PDF to BMP", + "subtitle": "Convert each PDF page into a BMP image." + }, + "pdfToTiff": { + "name": "PDF to TIFF", + "subtitle": "Convert each PDF page into a TIFF image." + }, + "pdfToGreyscale": { + "name": "PDF to Greyscale", + "subtitle": "Convert all colors to black and white." + }, + "pdfToJson": { + "name": "PDF to JSON", + "subtitle": "Convert PDF files to JSON format." + }, + "ocrPdf": { + "name": "OCR PDF", + "subtitle": "Make a PDF searchable and copyable." + }, + "alternateMix": { + "name": "Alternate & Mix Pages", + "subtitle": "Merge PDFs by alternating pages from each PDF. Preserves Bookmarks." + }, + "addAttachments": { + "name": "Add Attachments", + "subtitle": "Embed one or more files into your PDF." + }, + "extractAttachments": { + "name": "Extract Attachments", + "subtitle": "Extract all embedded files from PDF(s) as a ZIP." + }, + "editAttachments": { + "name": "Edit Attachments", + "subtitle": "View or remove attachments in your PDF." + }, + "dividePages": { + "name": "Divide Pages", + "subtitle": "Divide pages horizontally or vertically." + }, + "addBlankPage": { + "name": "Add Blank Page", + "subtitle": "Insert an empty page anywhere in your PDF." + }, + "reversePages": { + "name": "Reverse Pages", + "subtitle": "Flip the order of all pages in your document." + }, + "rotatePdf": { + "name": "Rotate PDF", + "subtitle": "Turn pages in 90-degree increments." + }, + "rotateCustom": { + "name": "Rotate by Custom Degrees", + "subtitle": "Rotate pages by any custom angle." + }, + "nUpPdf": { + "name": "N-Up PDF", + "subtitle": "Arrange multiple pages onto a single sheet." + }, + "combineToSinglePage": { + "name": "Combine to Single Page", + "subtitle": "Stitch all pages into one continuous scroll." + }, + "viewMetadata": { + "name": "View Metadata", + "subtitle": "Inspect the hidden properties of your PDF." + }, + "editMetadata": { + "name": "Edit Metadata", + "subtitle": "Change the author, title, and other properties." + }, + "pdfsToZip": { + "name": "PDFs to ZIP", + "subtitle": "Package multiple PDF files into a ZIP archive." + }, + "comparePdfs": { + "name": "Compare PDFs", + "subtitle": "Compare two PDFs side by side." + }, + "posterizePdf": { + "name": "Posterize PDF", + "subtitle": "Split a large page into multiple smaller pages." + }, + "fixPageSize": { + "name": "Fix Page Size", + "subtitle": "Standardize all pages to a uniform size." + }, + "linearizePdf": { + "name": "Linearize PDF", + "subtitle": "Optimize PDF for fast web viewing." + }, + "pageDimensions": { + "name": "Page Dimensions", + "subtitle": "Analyze page size, orientation, and units." + }, + "removeRestrictions": { + "name": "Remove Restrictions", + "subtitle": "Remove password protection and security restrictions associated with digitally signed PDF files." + }, + "repairPdf": { + "name": "Repair PDF", + "subtitle": "Recover data from corrupted or damaged PDF files." + }, + "encryptPdf": { + "name": "Encrypt PDF", + "subtitle": "Lock your PDF by adding a password." + }, + "sanitizePdf": { + "name": "Sanitize PDF", + "subtitle": "Remove metadata, annotations, scripts, and more." + }, + "decryptPdf": { + "name": "Decrypt PDF", + "subtitle": "Unlock PDF by removing password protection." + }, + "flattenPdf": { + "name": "Flatten PDF", + "subtitle": "Make form fields and annotations non-editable." + }, + "removeMetadata": { + "name": "Remove Metadata", + "subtitle": "Strip hidden data from your PDF." + }, + "changePermissions": { + "name": "Change Permissions", + "subtitle": "Set or change user permissions on a PDF." + }, + "odtToPdf": { + "name": "ODT to PDF", + "subtitle": "Convert OpenDocument Text files to PDF format. Supports multiple files.", + "acceptedFormats": "ODT files", + "convertButton": "Convert to PDF" + }, + "csvToPdf": { + "name": "CSV to PDF", + "subtitle": "Convert CSV spreadsheet files to PDF format. Supports multiple files.", + "acceptedFormats": "CSV files", + "convertButton": "Convert to PDF" + }, + "rtfToPdf": { + "name": "RTF to PDF", + "subtitle": "Convert Rich Text Format documents to PDF. Supports multiple files.", + "acceptedFormats": "RTF files", + "convertButton": "Convert to PDF" + }, + "wordToPdf": { + "name": "Word to PDF", + "subtitle": "Convert Word documents (DOCX, DOC, ODT, RTF) to PDF format. Supports multiple files.", + "acceptedFormats": "DOCX, DOC, ODT, RTF files", + "convertButton": "Convert to PDF" + }, + "excelToPdf": { + "name": "Excel to PDF", + "subtitle": "Convert Excel spreadsheets (XLSX, XLS, ODS, CSV) to PDF format. Supports multiple files.", + "acceptedFormats": "XLSX, XLS, ODS, CSV files", + "convertButton": "Convert to PDF" + }, + "powerpointToPdf": { + "name": "PowerPoint to PDF", + "subtitle": "Convert PowerPoint presentations (PPTX, PPT, ODP) to PDF format. Supports multiple files.", + "acceptedFormats": "PPTX, PPT, ODP files", + "convertButton": "Convert to PDF" + }, + "markdownToPdf": { + "name": "Markdown to PDF", + "subtitle": "Write or paste Markdown and export it as a beautifully formatted PDF.", + "paneMarkdown": "Markdown", + "panePreview": "Preview", + "btnUpload": "Upload", + "btnSyncScroll": "Sync Scroll", + "btnSettings": "Settings", + "btnExportPdf": "Export PDF", + "settingsTitle": "Markdown Settings", + "settingsPreset": "Preset", + "presetDefault": "Default (GFM-like)", + "presetCommonmark": "CommonMark (strict)", + "presetZero": "Minimal (no features)", + "settingsOptions": "Markdown Options", + "optAllowHtml": "Allow HTML tags", + "optBreaks": "Convert newlines to
", + "optLinkify": "Auto-convert URLs to links", + "optTypographer": "Typographer (smart quotes, etc.)" + }, + "pdfBooklet": { + "name": "PDF Booklet", + "subtitle": "Rearrange pages for double-sided booklet printing. Fold and staple to create a booklet.", + "howItWorks": "How it works:", + "step1": "Upload a PDF file.", + "step2": "Pages will be rearranged in booklet order.", + "step3": "Print double-sided, flip on short edge, fold and staple.", + "paperSize": "Paper Size", + "orientation": "Orientation", + "portrait": "Portrait", + "landscape": "Landscape", + "pagesPerSheet": "Pages per Sheet", + "createBooklet": "Create Booklet", + "processing": "Processing...", + "pageCount": "Page count will be padded to multiple of 4 if needed." + }, + "xpsToPdf": { + "name": "XPS to PDF", + "subtitle": "Convert XPS/OXPS documents to PDF format. Supports multiple files.", + "acceptedFormats": "XPS, OXPS files", + "convertButton": "Convert to PDF" + }, + "mobiToPdf": { + "name": "MOBI to PDF", + "subtitle": "Convert MOBI e-books to PDF format. Supports multiple files.", + "acceptedFormats": "MOBI files", + "convertButton": "Convert to PDF" + }, + "epubToPdf": { + "name": "EPUB to PDF", + "subtitle": "Convert EPUB e-books to PDF format. Supports multiple files.", + "acceptedFormats": "EPUB files", + "convertButton": "Convert to PDF" + }, + "fb2ToPdf": { + "name": "FB2 to PDF", + "subtitle": "Convert FictionBook (FB2) e-books to PDF format. Supports multiple files.", + "acceptedFormats": "FB2 files", + "convertButton": "Convert to PDF" + }, + "cbzToPdf": { + "name": "CBZ to PDF", + "subtitle": "Convert comic book archives (CBZ/CBR) to PDF format. Supports multiple files.", + "acceptedFormats": "CBZ, CBR files", + "convertButton": "Convert to PDF" + }, + "wpdToPdf": { + "name": "WPD to PDF", + "subtitle": "Convert WordPerfect documents (WPD) to PDF format. Supports multiple files.", + "acceptedFormats": "WPD files", + "convertButton": "Convert to PDF" + }, + "wpsToPdf": { + "name": "WPS to PDF", + "subtitle": "Convert WPS Office documents to PDF format. Supports multiple files.", + "acceptedFormats": "WPS files", + "convertButton": "Convert to PDF" + }, + "xmlToPdf": { + "name": "XML to PDF", + "subtitle": "Convert XML documents to PDF format. Supports multiple files.", + "acceptedFormats": "XML files", + "convertButton": "Convert to PDF" + }, + "pagesToPdf": { + "name": "Pages to PDF", + "subtitle": "Convert Apple Pages documents to PDF format. Supports multiple files.", + "acceptedFormats": "Pages files", + "convertButton": "Convert to PDF" + }, + "odgToPdf": { + "name": "ODG to PDF", + "subtitle": "Convert OpenDocument Graphics (ODG) files to PDF format. Supports multiple files.", + "acceptedFormats": "ODG files", + "convertButton": "Convert to PDF" + }, + "odsToPdf": { + "name": "ODS to PDF", + "subtitle": "Convert OpenDocument Spreadsheet (ODS) files to PDF format. Supports multiple files.", + "acceptedFormats": "ODS files", + "convertButton": "Convert to PDF" + }, + "odpToPdf": { + "name": "ODP to PDF", + "subtitle": "Convert OpenDocument Presentation (ODP) files to PDF format. Supports multiple files.", + "acceptedFormats": "ODP files", + "convertButton": "Convert to PDF" + }, + "pubToPdf": { + "name": "PUB to PDF", + "subtitle": "Convert Microsoft Publisher (PUB) files to PDF format. Supports multiple files.", + "acceptedFormats": "PUB files", + "convertButton": "Convert to PDF" + }, + "vsdToPdf": { + "name": "VSD to PDF", + "subtitle": "Convert Microsoft Visio (VSD, VSDX) files to PDF format. Supports multiple files.", + "acceptedFormats": "VSD, VSDX files", + "convertButton": "Convert to PDF" + }, + "psdToPdf": { + "name": "PSD to PDF", + "subtitle": "Convert Adobe Photoshop (PSD) files to PDF format. Supports multiple files.", + "acceptedFormats": "PSD files", + "convertButton": "Convert to PDF" + }, + "pdfToSvg": { + "name": "PDF to SVG", + "subtitle": "Convert each page of a PDF file into a scalable vector graphic (SVG) for perfect quality at any size." + }, + "extractTables": { + "name": "Extract PDF Tables", + "subtitle": "Extract tables from PDF files and export as CSV, JSON, or Markdown." + }, + "pdfToCsv": { + "name": "PDF to CSV", + "subtitle": "Extract tables from PDF and convert to CSV format." + }, + "pdfToExcel": { + "name": "PDF to Excel", + "subtitle": "Extract tables from PDF and convert to Excel (XLSX) format." + }, + "pdfToText": { + "name": "PDF to Text", + "subtitle": "Extract text from PDF files and save as plain text (.txt). Supports multiple files.", + "note": "This tool works ONLY with digitally created PDFs. For scanned documents or image-based PDFs, use our OCR PDF tool instead.", + "convertButton": "Extract Text" + }, + "digitalSignPdf": { + "name": "Digital Signature PDF", + "pageTitle": "Digital Signature PDF - Add Cryptographic Signature | BentoPDF", + "subtitle": "Add a cryptographic digital signature to your PDF using X.509 certificates. Supports PKCS#12 (.pfx, .p12) and PEM formats. Your private key never leaves your browser.", + "certificateSection": "Certificate", + "uploadCert": "Upload certificate (.pfx, .p12)", + "certPassword": "Certificate Password", + "certPasswordPlaceholder": "Enter certificate password", + "certInfo": "Certificate Information", + "certSubject": "Subject", + "certIssuer": "Issuer", + "certValidity": "Valid", + "signatureDetails": "Signature Details (Optional)", + "reason": "Reason", + "reasonPlaceholder": "e.g., I approve this document", + "location": "Location", + "locationPlaceholder": "e.g., New York, USA", + "contactInfo": "Contact Info", + "contactPlaceholder": "e.g., email@example.com", + "applySignature": "Apply Digital Signature", + "successMessage": "PDF signed successfully! The signature can be verified in any PDF reader." + }, + "validateSignaturePdf": { + "name": "Validate PDF Signature", + "pageTitle": "Validate PDF Signature - Verify Digital Signatures | BentoPDF", + "subtitle": "Verify digital signatures in your PDF files. Check certificate validity, view signer details, and confirm document integrity. All processing happens in your browser." + }, + "emailToPdf": { + "name": "Email to PDF", + "subtitle": "Convert email files (EML, MSG) to PDF format. Supports Outlook exports and standard email formats.", + "acceptedFormats": "EML, MSG files", + "convertButton": "Convert to PDF" + }, + "fontToOutline": { + "name": "Font to Outline", + "subtitle": "Convert all fonts to vector outlines for consistent rendering across all devices." + }, + "deskewPdf": { + "name": "Deskew PDF", + "subtitle": "Automatically straighten tilted scanned pages using OpenCV." + } +} diff --git a/public/locales/es/common.json b/public/locales/es/common.json new file mode 100644 index 0000000..a502855 --- /dev/null +++ b/public/locales/es/common.json @@ -0,0 +1,323 @@ +{ + "nav": { + "home": "Inicio", + "about": "Acerca de", + "contact": "Contacto", + "licensing": "Licencias", + "allTools": "Todas las Herramientas", + "openMainMenu": "Abrir menú principal", + "language": "Idioma" + }, + "donation": { + "message": "¿Te encanta BentoPDF? ¡Ayúdanos a mantenerlo gratis y de código abierto!", + "button": "Donar" + }, + "hero": { + "title": "El", + "pdfToolkit": "Kit de Herramientas PDF", + "builtForPrivacy": "diseñado para la privacidad", + "noSignups": "Sin Registro", + "unlimitedUse": "Uso Ilimitado", + "worksOffline": "Funciona Sin Conexión", + "startUsing": "Comenzar a Usar Ahora" + }, + "usedBy": { + "title": "Usado por empresas y personas que trabajan en" + }, + "features": { + "title": "¿Por qué elegir", + "bentoPdf": "BentoPDF?", + "noSignup": { + "title": "Sin Registro", + "description": "Comienza al instante, sin cuentas ni correos electrónicos." + }, + "noUploads": { + "title": "Sin Cargas", + "description": "100% del lado del cliente, tus archivos nunca salen de tu dispositivo." + }, + "foreverFree": { + "title": "Gratis para Siempre", + "description": "Todas las herramientas, sin pruebas, sin restricciones de pago." + }, + "noLimits": { + "title": "Sin Límites", + "description": "Usa tanto como quieras, sin límites ocultos." + }, + "batchProcessing": { + "title": "Procesamiento por Lotes", + "description": "Maneja PDFs ilimitados de una sola vez." + }, + "lightningFast": { + "title": "Ultrarrápido", + "description": "Procesa PDFs al instante, sin esperas ni retrasos." + } + }, + "tools": { + "title": "Comienza con", + "toolsLabel": "Herramientas", + "subtitle": "Haz clic en una herramienta para abrir el cargador de archivos", + "searchPlaceholder": "Buscar una herramienta (ej., 'dividir', 'organizar'...)", + "backToTools": "Volver a Herramientas", + "firstLoadNotice": "La primera carga toma un momento mientras descargamos nuestro motor de conversión. Después de eso, todas las cargas serán instantáneas." + }, + "upload": { + "clickToSelect": "Haz clic para seleccionar un archivo", + "orDragAndDrop": "o arrastra y suelta", + "pdfOrImages": "PDFs o Imágenes", + "filesNeverLeave": "Tus archivos nunca salen de tu dispositivo.", + "addMore": "Agregar Más Archivos", + "clearAll": "Limpiar Todo" + }, + "loader": { + "processing": "Procesando..." + }, + "alert": { + "title": "Alerta", + "ok": "OK" + }, + "preview": { + "title": "Vista Previa del Documento", + "downloadAsPdf": "Descargar como PDF", + "close": "Cerrar" + }, + "settings": { + "title": "Configuración", + "shortcuts": "Atajos", + "preferences": "Preferencias", + "displayPreferences": "Preferencias de Visualización", + "searchShortcuts": "Buscar atajos...", + "shortcutsInfo": "Mantén presionadas las teclas para establecer un atajo. Los cambios se guardan automáticamente.", + "shortcutsWarning": "⚠️ Evita los atajos comunes del navegador (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N, etc.) ya que pueden no funcionar de manera confiable.", + "import": "Importar", + "export": "Exportar", + "resetToDefaults": "Restaurar Valores Predeterminados", + "fullWidthMode": "Modo de Ancho Completo", + "fullWidthDescription": "Usa el ancho completo de la pantalla para todas las herramientas en lugar de un contenedor centrado", + "settingsAutoSaved": "La configuración se guarda automáticamente", + "clickToSet": "Haz clic para establecer", + "pressKeys": "Presiona teclas...", + "warnings": { + "alreadyInUse": "Atajo Ya en Uso", + "assignedTo": "ya está asignado a:", + "chooseDifferent": "Por favor elige un atajo diferente.", + "reserved": "Advertencia de Atajo Reservado", + "commonlyUsed": "se usa comúnmente para:", + "unreliable": "Este atajo puede no funcionar de manera confiable o puede entrar en conflicto con el comportamiento del navegador/sistema.", + "useAnyway": "¿Quieres usarlo de todos modos?", + "resetTitle": "Restablecer Atajos", + "resetMessage": "¿Estás seguro de que quieres restablecer todos los atajos a los valores predeterminados?

Esta acción no se puede deshacer.", + "importSuccessTitle": "Importación Exitosa", + "importSuccessMessage": "¡Atajos importados exitosamente!", + "importFailTitle": "Importación Fallida", + "importFailMessage": "Error al importar atajos. Formato de archivo inválido." + } + }, + "warning": { + "title": "Advertencia", + "cancel": "Cancelar", + "proceed": "Continuar" + }, + "compliance": { + "title": "Tus datos nunca salen de tu dispositivo", + "weKeep": "Mantenemos", + "yourInfoSafe": "tu información segura", + "byFollowingStandards": "siguiendo estándares de seguridad globales.", + "processingLocal": "Todo el procesamiento ocurre localmente en tu dispositivo.", + "gdpr": { + "title": "Cumplimiento GDPR", + "description": "Protege los datos personales y la privacidad de las personas dentro de la Unión Europea." + }, + "ccpa": { + "title": "Cumplimiento CCPA", + "description": "Otorga a los residentes de California derechos sobre cómo se recopila, usa y comparte su información personal." + }, + "hipaa": { + "title": "Cumplimiento HIPAA", + "description": "Establece salvaguardas para el manejo de información de salud sensible en el sistema de atención médica de Estados Unidos." + } + }, + "faq": { + "title": "Preguntas", + "questions": "Frecuentes", + "isFree": { + "question": "¿BentoPDF es realmente gratis?", + "answer": "Sí, absolutamente. Todas las herramientas en BentoPDF son 100% gratuitas, sin límites de archivos, sin registro y sin marcas de agua. Creemos que todos merecen acceso a herramientas PDF simples y potentes sin un muro de pago." + }, + "areFilesSecure": { + "question": "¿Mis archivos están seguros? ¿Dónde se procesan?", + "answer": "Tus archivos están lo más seguros posible porque nunca salen de tu computadora. Todo el procesamiento ocurre directamente en tu navegador web (del lado del cliente). Nunca cargamos tus archivos a un servidor, por lo que mantienes total privacidad y control sobre tus documentos." + }, + "platforms": { + "question": "¿Funciona en Mac, Windows y Móvil?", + "answer": "¡Sí! Dado que BentoPDF se ejecuta completamente en tu navegador, funciona en cualquier sistema operativo con un navegador web moderno, incluyendo Windows, macOS, Linux, iOS y Android." + }, + "gdprCompliant": { + "question": "¿BentoPDF cumple con GDPR?", + "answer": "Sí. BentoPDF cumple completamente con GDPR. Dado que todo el procesamiento de archivos ocurre localmente en tu navegador y nunca recopilamos ni transmitimos tus archivos a ningún servidor, no tenemos acceso a tus datos. Esto garantiza que siempre tengas el control de tus documentos." + }, + "dataStorage": { + "question": "¿Almacenan o rastrean alguno de mis archivos?", + "answer": "No. Nunca almacenamos, rastreamos ni registramos tus archivos. Todo lo que haces en BentoPDF ocurre en la memoria de tu navegador y desaparece una vez que cierras la página. No hay cargas, no hay registros de historial y no hay servidores involucrados." + }, + "different": { + "question": "¿Qué hace que BentoPDF sea diferente de otras herramientas PDF?", + "answer": "La mayoría de las herramientas PDF cargan tus archivos a un servidor para procesarlos. BentoPDF nunca hace eso. Utilizamos tecnología web moderna y segura para procesar tus archivos directamente en tu navegador. Esto significa un rendimiento más rápido, mayor privacidad y total tranquilidad." + }, + "browserBased": { + "question": "¿Cómo me mantiene seguro el procesamiento basado en navegador?", + "answer": "Al ejecutarse completamente dentro de tu navegador, BentoPDF garantiza que tus archivos nunca salgan de tu dispositivo. Esto elimina los riesgos de hackeos de servidores, violaciones de datos o accesos no autorizados. Tus archivos siguen siendo tuyos, siempre." + }, + "analytics": { + "question": "¿Usan cookies o análisis para rastrearme?", + "answer": "Nos preocupamos por tu privacidad. BentoPDF no rastrea información personal. Usamos Simple Analytics únicamente para ver recuentos de visitas anónimas. Esto significa que podemos saber cuántos usuarios visitan nuestro sitio, pero nunca sabemos quién eres. Simple Analytics cumple completamente con GDPR y respeta tu privacidad." + } + }, + "testimonials": { + "title": "Lo que Nuestros", + "users": "Usuarios", + "say": "Dicen" + }, + "support": { + "title": "¿Te Gusta Mi Trabajo?", + "description": "BentoPDF es un proyecto de pasión, creado para proporcionar un kit de herramientas PDF gratuito, privado y potente para todos. Si te resulta útil, considera apoyar su desarrollo. ¡Cada café ayuda!", + "buyMeCoffee": "Cómprame un Café" + }, + "footer": { + "copyright": "© 2025 BentoPDF. Todos los derechos reservados.", + "version": "Versión", + "company": "Empresa", + "aboutUs": "Acerca de Nosotros", + "faqLink": "Preguntas Frecuentes", + "contactUs": "Contáctanos", + "legal": "Legal", + "termsAndConditions": "Términos y Condiciones", + "privacyPolicy": "Política de Privacidad", + "followUs": "Síguenos" + }, + "merge": { + "title": "Fusionar PDFs", + "description": "Combina archivos completos o selecciona páginas específicas para fusionar en un nuevo documento.", + "fileMode": "Modo Archivo", + "pageMode": "Modo Página", + "howItWorks": "Cómo funciona:", + "fileModeInstructions": [ + "Haz clic y arrastra el ícono para cambiar el orden de los archivos.", + "En el cuadro \"Páginas\" para cada archivo, puedes especificar rangos (ej., \"1-3, 5\") para fusionar solo esas páginas.", + "Deja el cuadro \"Páginas\" en blanco para incluir todas las páginas de ese archivo." + ], + "pageModeInstructions": [ + "Todas las páginas de tus PDFs cargados se muestran a continuación.", + "Simplemente arrastra y suelta las miniaturas de páginas individuales para crear el orden exacto que deseas para tu nuevo archivo." + ], + "mergePdfs": "Fusionar PDFs" + }, + "common": { + "page": "Página", + "pages": "Páginas", + "of": "de", + "download": "Descargar", + "cancel": "Cancelar", + "save": "Guardar", + "delete": "Eliminar", + "edit": "Editar", + "add": "Agregar", + "remove": "Remover", + "loading": "Cargando...", + "error": "Error", + "success": "Éxito", + "file": "Archivo", + "files": "Archivos" + }, + "about": { + "hero": { + "title": "Creemos que las herramientas PDF deben ser", + "subtitle": "rápidas, privadas y gratuitas.", + "noCompromises": "Sin compromisos." + }, + "mission": { + "title": "Nuestra Misión", + "description": "Proporcionar la caja de herramientas PDF más completa que respete tu privacidad y nunca pida pago. Creemos que las herramientas de documentos esenciales deben ser accesibles para todos, en todas partes, sin barreras." + }, + "philosophy": { + "label": "Nuestra Filosofía Central", + "title": "Privacidad Primero. Siempre.", + "description": "En una era donde los datos son una mercancía, adoptamos un enfoque diferente. Todo el procesamiento de las herramientas de Bentopdf ocurre localmente en tu navegador. Esto significa que tus archivos nunca tocan nuestros servidores, nunca vemos tus documentos y no rastreamos lo que haces. Tus documentos permanecen completa e inequívocamente privados. No es solo una característica; es nuestra base." + }, + "whyBentopdf": { + "title": "Por qué", + "speed": { + "title": "Diseñado para la Velocidad", + "description": "Sin esperar cargas o descargas a un servidor. Al procesar archivos directamente en tu navegador usando tecnologías web modernas como WebAssembly, ofrecemos una velocidad incomparable para todas nuestras herramientas." + }, + "free": { + "title": "Completamente Gratis", + "description": "Sin pruebas, sin suscripciones, sin tarifas ocultas y sin funciones \"premium\" retenidas como rehenes. Creemos que las herramientas PDF potentes deben ser una utilidad pública, no un centro de ganancias." + }, + "noAccount": { + "title": "No Requiere Cuenta", + "description": "Comienza a usar cualquier herramienta de inmediato. No necesitamos tu correo electrónico, una contraseña o cualquier información personal. Tu flujo de trabajo debe ser sin fricciones y anónimo." + }, + "openSource": { + "title": "Espíritu de Código Abierto", + "description": "Construido con transparencia en mente. Aprovechamos increíbles bibliotecas de código abierto como PDF-lib y PDF.js, y creemos en el esfuerzo impulsado por la comunidad para hacer que las herramientas potentes sean accesibles para todos." + } + }, + "cta": { + "title": "¿Listo para comenzar?", + "description": "Únete a miles de usuarios que confían en Bentopdf para sus necesidades diarias de documentos. Experimenta la diferencia que la privacidad y el rendimiento pueden hacer.", + "button": "Explorar Todas las Herramientas" + } + }, + "contact": { + "title": "Ponte en Contacto", + "subtitle": "Nos encantaría saber de ti. Ya sea que tengas una pregunta, comentario o solicitud de función, no dudes en comunicarte.", + "email": "Puedes contactarnos directamente por correo electrónico en:" + }, + "licensing": { + "title": "Licencias para", + "subtitle": "Elige la licencia que se ajuste a tus necesidades." + }, + "multiTool": { + "uploadPdfs": "Cargar PDFs", + "upload": "Cargar", + "addBlankPage": "Agregar Página en Blanco", + "edit": "Editar:", + "undo": "Deshacer", + "redo": "Rehacer", + "reset": "Restablecer", + "selection": "Selección:", + "selectAll": "Seleccionar Todo", + "deselectAll": "Deseleccionar Todo", + "rotate": "Rotar:", + "rotateLeft": "Izquierda", + "rotateRight": "Derecha", + "transform": "Transformar:", + "duplicate": "Duplicar", + "split": "Dividir", + "clear": "Limpiar:", + "delete": "Eliminar", + "download": "Descargar:", + "downloadSelected": "Descargar Seleccionados", + "exportPdf": "Exportar PDF", + "uploadPdfFiles": "Seleccionar Archivos PDF", + "dragAndDrop": "Arrastra y suelta archivos PDF aquí, o haz clic para seleccionar", + "selectFiles": "Seleccionar Archivos", + "renderingPages": "Renderizando páginas...", + "actions": { + "duplicatePage": "Duplicar esta página", + "deletePage": "Eliminar esta página", + "insertPdf": "Insertar PDF después de esta página", + "toggleSplit": "Alternar división después de esta página" + }, + "pleaseWait": "Por Favor Espera", + "pagesRendering": "Las páginas aún se están renderizando. Por favor espera...", + "noPagesSelected": "No Se Seleccionaron Páginas", + "selectOnePage": "Por favor selecciona al menos una página para descargar.", + "noPages": "Sin Páginas", + "noPagesToExport": "No hay páginas para exportar.", + "renderingTitle": "Renderizando vistas previas de páginas", + "errorRendering": "Error al renderizar miniaturas de páginas", + "error": "Error", + "failedToLoad": "Error al cargar" + } +} diff --git a/public/locales/es/tools.json b/public/locales/es/tools.json new file mode 100644 index 0000000..920aa57 --- /dev/null +++ b/public/locales/es/tools.json @@ -0,0 +1,533 @@ +{ + "categories": { + "popularTools": "Herramientas Populares", + "editAnnotate": "Editar y Anotar", + "convertToPdf": "Convertir a PDF", + "convertFromPdf": "Convertir desde PDF", + "organizeManage": "Organizar y Gestionar", + "optimizeRepair": "Optimizar y Reparar", + "securePdf": "Asegurar PDF" + }, + "pdfMultiTool": { + "name": "Multiherramienta PDF", + "subtitle": "Fusionar, Dividir, Organizar, Eliminar, Rotar, Agregar Páginas en Blanco, Extraer y Duplicar en una interfaz unificada." + }, + "mergePdf": { + "name": "Fusionar PDF", + "subtitle": "Combina múltiples PDFs en un solo archivo. Preserva Marcadores." + }, + "splitPdf": { + "name": "Dividir PDF", + "subtitle": "Extrae un rango de páginas en un nuevo PDF." + }, + "compressPdf": { + "name": "Comprimir PDF", + "subtitle": "Reduce el tamaño de archivo de tu PDF.", + "algorithmLabel": "Algoritmo de Compresión", + "condense": "Condensar (Recomendado)", + "photon": "Photon (Para PDFs con Muchas Fotos)", + "condenseInfo": "Condensar usa compresión avanzada: elimina peso muerto, optimiza imágenes, reduce fuentes. Mejor para la mayoría de PDFs.", + "photonInfo": "Photon convierte páginas en imágenes. Úsalo para PDFs con muchas fotos/escaneados.", + "photonWarning": "Advertencia: El texto dejará de ser seleccionable y los enlaces dejarán de funcionar.", + "levelLabel": "Nivel de Compresión", + "light": "Ligero (Preservar Calidad)", + "balanced": "Equilibrado (Recomendado)", + "aggressive": "Agresivo (Archivos Más Pequeños)", + "extreme": "Extremo (Compresión Máxima)", + "grayscale": "Convertir a Escala de Grises", + "grayscaleHint": "Reduce el tamaño del archivo eliminando información de color", + "customSettings": "Configuración Personalizada", + "customSettingsHint": "Ajusta los parámetros de compresión:", + "outputQuality": "Calidad de Salida", + "resizeImagesTo": "Redimensionar Imágenes a", + "onlyProcessAbove": "Solo Procesar Arriba de", + "removeMetadata": "Eliminar metadatos", + "subsetFonts": "Reducir fuentes (eliminar glifos no usados)", + "removeThumbnails": "Eliminar miniaturas incrustadas", + "compressButton": "Comprimir PDF" + }, + "pdfEditor": { + "name": "Editor PDF", + "subtitle": "Anotar, resaltar, redactar, comentar, agregar formas/imágenes, buscar y ver PDFs." + }, + "jpgToPdf": { + "name": "JPG a PDF", + "subtitle": "Crea un PDF desde imágenes JPG, JPEG y JPEG2000 (JP2/JPX)." + }, + "signPdf": { + "name": "Firmar PDF", + "subtitle": "Dibuja, escribe o carga tu firma." + }, + "cropPdf": { + "name": "Recortar PDF", + "subtitle": "Recorta los márgenes de cada página en tu PDF." + }, + "extractPages": { + "name": "Extraer Páginas", + "subtitle": "Guarda una selección de páginas como nuevos archivos." + }, + "duplicateOrganize": { + "name": "Duplicar y Organizar", + "subtitle": "Duplica, reordena y elimina páginas." + }, + "deletePages": { + "name": "Eliminar Páginas", + "subtitle": "Elimina páginas específicas de tu documento." + }, + "editBookmarks": { + "name": "Editar Marcadores", + "subtitle": "Agrega, edita, importa, elimina y extrae marcadores PDF." + }, + "tableOfContents": { + "name": "Tabla de Contenidos", + "subtitle": "Genera una página de tabla de contenidos desde los marcadores PDF." + }, + "pageNumbers": { + "name": "Números de Página", + "subtitle": "Inserta números de página en tu documento." + }, + "addWatermark": { + "name": "Agregar Marca de Agua", + "subtitle": "Estampa texto o una imagen sobre tus páginas PDF." + }, + "headerFooter": { + "name": "Encabezado y Pie de Página", + "subtitle": "Agrega texto en la parte superior e inferior de las páginas." + }, + "invertColors": { + "name": "Invertir Colores", + "subtitle": "Crea una versión en \"modo oscuro\" de tu PDF." + }, + "backgroundColor": { + "name": "Color de Fondo", + "subtitle": "Cambia el color de fondo de tu PDF." + }, + "changeTextColor": { + "name": "Cambiar Color de Texto", + "subtitle": "Cambia el color del texto en tu PDF." + }, + "addStamps": { + "name": "Agregar Sellos", + "subtitle": "Agrega sellos de imagen a tu PDF usando la barra de herramientas de anotación.", + "usernameLabel": "Nombre de Usuario del Sello", + "usernamePlaceholder": "Ingresa tu nombre (para sellos)", + "usernameHint": "Este nombre aparecerá en los sellos que crees." + }, + "removeAnnotations": { + "name": "Eliminar Anotaciones", + "subtitle": "Elimina comentarios, resaltados y enlaces." + }, + "pdfFormFiller": { + "name": "Rellenar Formularios PDF", + "subtitle": "Rellena formularios directamente en el navegador. También soporta formularios XFA." + }, + "createPdfForm": { + "name": "Crear Formulario PDF", + "subtitle": "Crea formularios PDF rellenables con campos de texto arrastrables." + }, + "removeBlankPages": { + "name": "Eliminar Páginas en Blanco", + "subtitle": "Detecta y elimina automáticamente páginas en blanco." + }, + "imageToPdf": { + "name": "Imágenes a PDF", + "subtitle": "Convierte JPG, PNG, BMP, GIF, TIFF, PNM, PGM, PBM, PPM, PAM, JXR, JPX, JP2, PSD, SVG, HEIC, WebP a PDF." + }, + "pngToPdf": { + "name": "PNG a PDF", + "subtitle": "Crea un PDF desde una o más imágenes PNG." + }, + "webpToPdf": { + "name": "WebP a PDF", + "subtitle": "Crea un PDF desde una o más imágenes WebP." + }, + "svgToPdf": { + "name": "SVG a PDF", + "subtitle": "Crea un PDF desde una o más imágenes SVG." + }, + "bmpToPdf": { + "name": "BMP a PDF", + "subtitle": "Crea un PDF desde una o más imágenes BMP." + }, + "heicToPdf": { + "name": "HEIC a PDF", + "subtitle": "Crea un PDF desde una o más imágenes HEIC." + }, + "tiffToPdf": { + "name": "TIFF a PDF", + "subtitle": "Crea un PDF desde una o más imágenes TIFF." + }, + "textToPdf": { + "name": "Texto a PDF", + "subtitle": "Convierte un archivo de texto plano en un PDF." + }, + "jsonToPdf": { + "name": "JSON a PDF", + "subtitle": "Convierte archivos JSON a formato PDF." + }, + "pdfToJpg": { + "name": "PDF a JPG", + "subtitle": "Convierte cada página PDF en una imagen JPG." + }, + "pdfToPng": { + "name": "PDF a PNG", + "subtitle": "Convierte cada página PDF en una imagen PNG." + }, + "pdfToWebp": { + "name": "PDF a WebP", + "subtitle": "Convierte cada página PDF en una imagen WebP." + }, + "pdfToBmp": { + "name": "PDF a BMP", + "subtitle": "Convierte cada página PDF en una imagen BMP." + }, + "pdfToTiff": { + "name": "PDF a TIFF", + "subtitle": "Convierte cada página PDF en una imagen TIFF." + }, + "pdfToGreyscale": { + "name": "PDF a Escala de Grises", + "subtitle": "Convierte todos los colores a blanco y negro." + }, + "pdfToJson": { + "name": "PDF a JSON", + "subtitle": "Convierte archivos PDF a formato JSON." + }, + "ocrPdf": { + "name": "OCR PDF", + "subtitle": "Hace que un PDF sea buscable y copiable." + }, + "alternateMix": { + "name": "Alternar y Mezclar Páginas", + "subtitle": "Fusiona PDFs alternando páginas de cada PDF. Preserva Marcadores." + }, + "addAttachments": { + "name": "Agregar Adjuntos", + "subtitle": "Incrusta uno o más archivos en tu PDF." + }, + "extractAttachments": { + "name": "Extraer Adjuntos", + "subtitle": "Extrae todos los archivos incrustados de PDF(s) como un ZIP." + }, + "editAttachments": { + "name": "Editar Adjuntos", + "subtitle": "Ve o elimina adjuntos en tu PDF." + }, + "dividePages": { + "name": "Dividir Páginas", + "subtitle": "Divide páginas horizontal o verticalmente." + }, + "addBlankPage": { + "name": "Agregar Página en Blanco", + "subtitle": "Inserta una página vacía en cualquier lugar de tu PDF." + }, + "reversePages": { + "name": "Invertir Páginas", + "subtitle": "Invierte el orden de todas las páginas en tu documento." + }, + "rotatePdf": { + "name": "Rotar PDF", + "subtitle": "Gira páginas en incrementos de 90 grados." + }, + "rotateCustom": { + "name": "Rotar por Grados Personalizados", + "subtitle": "Rota páginas por cualquier ángulo personalizado." + }, + "nUpPdf": { + "name": "N-Up PDF", + "subtitle": "Organiza múltiples páginas en una sola hoja." + }, + "combineToSinglePage": { + "name": "Combinar en Una Sola Página", + "subtitle": "Une todas las páginas en un desplazamiento continuo." + }, + "viewMetadata": { + "name": "Ver Metadatos", + "subtitle": "Inspecciona las propiedades ocultas de tu PDF." + }, + "editMetadata": { + "name": "Editar Metadatos", + "subtitle": "Cambia el autor, título y otras propiedades." + }, + "pdfsToZip": { + "name": "PDFs a ZIP", + "subtitle": "Empaqueta múltiples archivos PDF en un archivo ZIP." + }, + "comparePdfs": { + "name": "Comparar PDFs", + "subtitle": "Compara dos PDFs lado a lado." + }, + "posterizePdf": { + "name": "Posterizar PDF", + "subtitle": "Divide una página grande en múltiples páginas más pequeñas." + }, + "fixPageSize": { + "name": "Fijar Tamaño de Página", + "subtitle": "Estandariza todas las páginas a un tamaño uniforme." + }, + "linearizePdf": { + "name": "Linealizar PDF", + "subtitle": "Optimiza el PDF para visualización web rápida." + }, + "pageDimensions": { + "name": "Dimensiones de Página", + "subtitle": "Analiza el tamaño, orientación y unidades de página." + }, + "removeRestrictions": { + "name": "Eliminar Restricciones", + "subtitle": "Elimina la protección por contraseña y las restricciones de seguridad asociadas con archivos PDF firmados digitalmente." + }, + "repairPdf": { + "name": "Reparar PDF", + "subtitle": "Recupera datos de archivos PDF corruptos o dañados." + }, + "encryptPdf": { + "name": "Cifrar PDF", + "subtitle": "Bloquea tu PDF agregando una contraseña." + }, + "sanitizePdf": { + "name": "Sanear PDF", + "subtitle": "Elimina metadatos, anotaciones, scripts y más." + }, + "decryptPdf": { + "name": "Descifrar PDF", + "subtitle": "Desbloquea PDF eliminando la protección por contraseña." + }, + "flattenPdf": { + "name": "Aplanar PDF", + "subtitle": "Hace que los campos de formulario y las anotaciones no sean editables." + }, + "removeMetadata": { + "name": "Eliminar Metadatos", + "subtitle": "Elimina datos ocultos de tu PDF." + }, + "changePermissions": { + "name": "Cambiar Permisos", + "subtitle": "Establece o cambia los permisos de usuario en un PDF." + }, + "odtToPdf": { + "name": "ODT a PDF", + "subtitle": "Convierte archivos OpenDocument Text a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos ODT", + "convertButton": "Convertir a PDF" + }, + "csvToPdf": { + "name": "CSV a PDF", + "subtitle": "Convierte archivos de hoja de cálculo CSV a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos CSV", + "convertButton": "Convertir a PDF" + }, + "rtfToPdf": { + "name": "RTF a PDF", + "subtitle": "Convierte documentos Rich Text Format a PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos RTF", + "convertButton": "Convertir a PDF" + }, + "wordToPdf": { + "name": "Word a PDF", + "subtitle": "Convierte documentos Word (DOCX, DOC, ODT, RTF) a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos DOCX, DOC, ODT, RTF", + "convertButton": "Convertir a PDF" + }, + "excelToPdf": { + "name": "Excel a PDF", + "subtitle": "Convierte hojas de cálculo Excel (XLSX, XLS, ODS, CSV) a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos XLSX, XLS, ODS, CSV", + "convertButton": "Convertir a PDF" + }, + "powerpointToPdf": { + "name": "PowerPoint a PDF", + "subtitle": "Convierte presentaciones PowerPoint (PPTX, PPT, ODP) a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos PPTX, PPT, ODP", + "convertButton": "Convertir a PDF" + }, + "markdownToPdf": { + "name": "Markdown a PDF", + "subtitle": "Escribe o pega Markdown y expórtalo como un PDF bellamente formateado.", + "paneMarkdown": "Markdown", + "panePreview": "Vista Previa", + "btnUpload": "Cargar", + "btnSyncScroll": "Sincronizar Desplazamiento", + "btnSettings": "Configuración", + "btnExportPdf": "Exportar PDF", + "settingsTitle": "Configuración de Markdown", + "settingsPreset": "Predefinido", + "presetDefault": "Predeterminado (similar a GFM)", + "presetCommonmark": "CommonMark (estricto)", + "presetZero": "Mínimo (sin funciones)", + "settingsOptions": "Opciones de Markdown", + "optAllowHtml": "Permitir etiquetas HTML", + "optBreaks": "Convertir saltos de línea a
", + "optLinkify": "Auto-convertir URLs a enlaces", + "optTypographer": "Tipógrafo (comillas inteligentes, etc.)" + }, + "pdfBooklet": { + "name": "Folleto PDF", + "subtitle": "Reorganiza páginas para impresión de folleto a doble cara. Dobla y engrapa para crear un folleto.", + "howItWorks": "Cómo funciona:", + "step1": "Carga un archivo PDF.", + "step2": "Las páginas se reorganizarán en orden de folleto.", + "step3": "Imprime a doble cara, voltea por el borde corto, dobla y engrapa.", + "paperSize": "Tamaño de Papel", + "orientation": "Orientación", + "portrait": "Vertical", + "landscape": "Horizontal", + "pagesPerSheet": "Páginas por Hoja", + "createBooklet": "Crear Folleto", + "processing": "Procesando...", + "pageCount": "El recuento de páginas se rellenará a múltiplo de 4 si es necesario." + }, + "xpsToPdf": { + "name": "XPS a PDF", + "subtitle": "Convierte documentos XPS/OXPS a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos XPS, OXPS", + "convertButton": "Convertir a PDF" + }, + "mobiToPdf": { + "name": "MOBI a PDF", + "subtitle": "Convierte e-books MOBI a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos MOBI", + "convertButton": "Convertir a PDF" + }, + "epubToPdf": { + "name": "EPUB a PDF", + "subtitle": "Convierte e-books EPUB a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos EPUB", + "convertButton": "Convertir a PDF" + }, + "fb2ToPdf": { + "name": "FB2 a PDF", + "subtitle": "Convierte e-books FictionBook (FB2) a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos FB2", + "convertButton": "Convertir a PDF" + }, + "cbzToPdf": { + "name": "CBZ a PDF", + "subtitle": "Convierte archivos de cómics (CBZ/CBR) a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos CBZ, CBR", + "convertButton": "Convertir a PDF" + }, + "wpdToPdf": { + "name": "WPD a PDF", + "subtitle": "Convierte documentos WordPerfect (WPD) a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos WPD", + "convertButton": "Convertir a PDF" + }, + "wpsToPdf": { + "name": "WPS a PDF", + "subtitle": "Convierte documentos WPS Office a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos WPS", + "convertButton": "Convertir a PDF" + }, + "xmlToPdf": { + "name": "XML a PDF", + "subtitle": "Convierte documentos XML a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos XML", + "convertButton": "Convertir a PDF" + }, + "pagesToPdf": { + "name": "Pages a PDF", + "subtitle": "Convierte documentos Apple Pages a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos Pages", + "convertButton": "Convertir a PDF" + }, + "odgToPdf": { + "name": "ODG a PDF", + "subtitle": "Convierte archivos OpenDocument Graphics (ODG) a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos ODG", + "convertButton": "Convertir a PDF" + }, + "odsToPdf": { + "name": "ODS a PDF", + "subtitle": "Convierte archivos OpenDocument Spreadsheet (ODS) a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos ODS", + "convertButton": "Convertir a PDF" + }, + "odpToPdf": { + "name": "ODP a PDF", + "subtitle": "Convierte archivos OpenDocument Presentation (ODP) a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos ODP", + "convertButton": "Convertir a PDF" + }, + "pubToPdf": { + "name": "PUB a PDF", + "subtitle": "Convierte archivos Microsoft Publisher (PUB) a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos PUB", + "convertButton": "Convertir a PDF" + }, + "vsdToPdf": { + "name": "VSD a PDF", + "subtitle": "Convierte archivos Microsoft Visio (VSD, VSDX) a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos VSD, VSDX", + "convertButton": "Convertir a PDF" + }, + "psdToPdf": { + "name": "PSD a PDF", + "subtitle": "Convierte archivos Adobe Photoshop (PSD) a formato PDF. Soporta múltiples archivos.", + "acceptedFormats": "Archivos PSD", + "convertButton": "Convertir a PDF" + }, + "pdfToSvg": { + "name": "PDF a SVG", + "subtitle": "Convierte cada página de un archivo PDF en un gráfico vectorial escalable (SVG) para calidad perfecta a cualquier tamaño." + }, + "extractTables": { + "name": "Extraer Tablas de PDF", + "subtitle": "Extrae tablas de archivos PDF y exporta como CSV, JSON o Markdown." + }, + "pdfToCsv": { + "name": "PDF a CSV", + "subtitle": "Extrae tablas de PDF y convierte a formato CSV." + }, + "pdfToExcel": { + "name": "PDF a Excel", + "subtitle": "Extrae tablas de PDF y convierte a formato Excel (XLSX)." + }, + "pdfToText": { + "name": "PDF a Texto", + "subtitle": "Extrae texto de archivos PDF y guarda como texto plano (.txt). Soporta múltiples archivos.", + "note": "Esta herramienta funciona SOLO con PDFs creados digitalmente. Para documentos escaneados o PDFs basados en imágenes, usa nuestra herramienta OCR PDF en su lugar.", + "convertButton": "Extraer Texto" + }, + "digitalSignPdf": { + "name": "Firma Digital PDF", + "pageTitle": "Firma Digital PDF - Agregar Firma Criptográfica | BentoPDF", + "subtitle": "Agrega una firma digital criptográfica a tu PDF usando certificados X.509. Soporta formatos PKCS#12 (.pfx, .p12) y PEM. Tu clave privada nunca sale de tu navegador.", + "certificateSection": "Certificado", + "uploadCert": "Cargar certificado (.pfx, .p12)", + "certPassword": "Contraseña del Certificado", + "certPasswordPlaceholder": "Ingresa la contraseña del certificado", + "certInfo": "Información del Certificado", + "certSubject": "Sujeto", + "certIssuer": "Emisor", + "certValidity": "Válido", + "signatureDetails": "Detalles de la Firma (Opcional)", + "reason": "Razón", + "reasonPlaceholder": "ej., Apruebo este documento", + "location": "Ubicación", + "locationPlaceholder": "ej., Madrid, España", + "contactInfo": "Información de Contacto", + "contactPlaceholder": "ej., email@ejemplo.com", + "applySignature": "Aplicar Firma Digital", + "successMessage": "¡PDF firmado exitosamente! La firma se puede verificar en cualquier lector de PDF." + }, + "validateSignaturePdf": { + "name": "Validar Firma PDF", + "pageTitle": "Validar Firma PDF - Verificar Firmas Digitales | BentoPDF", + "subtitle": "Verifica firmas digitales en tus archivos PDF. Comprueba la validez del certificado, ve los detalles del firmante y confirma la integridad del documento." + }, + "emailToPdf": { + "name": "Email a PDF", + "subtitle": "Convierte archivos de correo (EML, MSG) a formato PDF. Soporta exportaciones de Outlook y formatos de correo estándar.", + "acceptedFormats": "Archivos EML, MSG", + "convertButton": "Convertir a PDF" + }, + "fontToOutline": { + "name": "Fuente a Contorno", + "subtitle": "Convierte todas las fuentes a contornos vectoriales para una renderización consistente en todos los dispositivos." + }, + "deskewPdf": { + "name": "Enderezar PDF", + "subtitle": "Endereza automáticamente páginas escaneadas inclinadas usando OpenCV." + } +} diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json new file mode 100644 index 0000000..fa7aec2 --- /dev/null +++ b/public/locales/fr/common.json @@ -0,0 +1,323 @@ +{ + "nav": { + "home": "Accueil", + "about": "À propos", + "contact": "Contact", + "licensing": "Licence", + "allTools": "Tous les outils", + "openMainMenu": "Ouvrir le menu principal", + "language": "Langue" + }, + "donation": { + "message": "Vous aimez BentoPDF ? Aidez-nous à le garder open source !", + "button": "Soutenir" + }, + "hero": { + "title": "La", + "pdfToolkit": "palette d’outils PDF", + "builtForPrivacy": "conçue pour la confidentialité", + "noSignups": "Sans inscription", + "unlimitedUse": "Utilisation illimitée", + "worksOffline": "Fonctionne hors ligne", + "startUsing": "Commencer maintenant" + }, + "usedBy": { + "title": "Utilisé par des entreprises et des professionnels de" + }, + "features": { + "title": "Pourquoi choisir", + "bentoPdf": "BentoPDF ?", + "noSignup": { + "title": "Sans inscription", + "description": "Utilisation immédiate, sans compte ni email." + }, + "noUploads": { + "title": "Aucun envoi de fichiers", + "description": "100 % côté navigateur, vos fichiers ne quittent jamais votre appareil." + }, + "foreverFree": { + "title": "Gratuit pour toujours", + "description": "Tous les outils, sans essai, sans paiement, sans restrictions." + }, + "noLimits": { + "title": "Sans limites", + "description": "Utilisez autant que vous voulez, sans plafonds cachés." + }, + "batchProcessing": { + "title": "Traitement par lots", + "description": "Gérez un nombre illimité de PDF en une seule fois." + }, + "lightningFast": { + "title": "Ultra rapide", + "description": "Traitez vos PDF instantanément, sans attente." + } + }, + "tools": { + "title": "Commencer avec", + "toolsLabel": "Les outils", + "subtitle": "Cliquez sur un outil pour importer vos fichiers", + "searchPlaceholder": "Rechercher un outil (ex. « scinder », « organiser »...)", + "backToTools": "Retour aux outils", + "firstLoadNotice": "Le premier chargement peut prendre quelques instants, le temps de charger notre moteur de conversion. Les prochaines fois, tout se chargera instantanément." + }, + "upload": { + "clickToSelect": "Cliquez pour sélectionner un fichier", + "orDragAndDrop": "ou glissez-déposez", + "pdfOrImages": "PDF ou images", + "filesNeverLeave": "Vos fichiers restent sur votre appareil.", + "addMore": "Ajouter d’autres fichiers", + "clearAll": "Tout effacer" + }, + "loader": { + "processing": "Traitement en cours..." + }, + "alert": { + "title": "Alerte", + "ok": "OK" + }, + "preview": { + "title": "Aperçu du document", + "downloadAsPdf": "Télécharger en PDF", + "close": "Fermer" + }, + "settings": { + "title": "Paramètres", + "shortcuts": "Raccourcis", + "preferences": "Préférences", + "displayPreferences": "Préférences d’affichage", + "searchShortcuts": "Rechercher un raccourci...", + "shortcutsInfo": "Maintenez les touches pour définir un raccourci. Les changements sont enregistrés automatiquement.", + "shortcutsWarning": "⚠️ Évitez les raccourcis courants du navigateur (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N, etc.), ils peuvent ne pas fonctionner correctement.", + "import": "Importer", + "export": "Exporter", + "resetToDefaults": "Rétablir les paramètres par défaut", + "fullWidthMode": "Mode pleine largeur", + "fullWidthDescription": "Utiliser toute la largeur de l’écran au lieu d’un affichage centré", + "settingsAutoSaved": "Les paramètres sont enregistrés automatiquement", + "clickToSet": "Cliquez pour définir", + "pressKeys": "Appuyez sur les touches...", + "warnings": { + "alreadyInUse": "Raccourci déjà utilisé", + "assignedTo": "est déjà attribué à :", + "chooseDifferent": "Veuillez choisir un autre raccourci.", + "reserved": "Avertissement de raccourci réservé", + "commonlyUsed": "est couramment utilisé pour :", + "unreliable": "Ce raccourci peut ne pas fonctionner correctement ou entrer en conflit avec le navigateur ou le système.", + "useAnyway": "Souhaitez-vous l’utiliser quand même ?", + "resetTitle": "Réinitialiser les raccourcis", + "resetMessage": "Êtes-vous sûr de vouloir réinitialiser tous les raccourcis par défaut ?

Cette action est irréversible.", + "importSuccessTitle": "Importation réussie", + "importSuccessMessage": "Les raccourcis ont été importés avec succès !", + "importFailTitle": "Échec de l’importation", + "importFailMessage": "Impossible d’importer les raccourcis. Format de fichier invalide." + } + }, + "warning": { + "title": "Attention", + "cancel": "Annuler", + "proceed": "Continuer" + }, + "compliance": { + "title": "Vos données ne quittent jamais votre appareil", + "weKeep": "Nous protégeons", + "yourInfoSafe": "vos informations", + "byFollowingStandards": "en respectant les normes de sécurité internationales.", + "processingLocal": "Tous les traitements sont effectués localement sur votre appareil.", + "gdpr": { + "title": "Conformité RGPD", + "description": "Protège les données personnelles et la vie privée des citoyens de l’Union européenne." + }, + "ccpa": { + "title": "Conformité CCPA", + "description": "Accorde aux résidents de Californie des droits sur l’utilisation de leurs données personnelles." + }, + "hipaa": { + "title": "Conformité HIPAA", + "description": "Définit des règles strictes pour la gestion des données de santé aux États-Unis." + } + }, + "faq": { + "title": "Questions", + "questions": "fréquentes", + "isFree": { + "question": "BentoPDF est-il vraiment gratuit ?", + "answer": "Oui, totalement. Tous les outils BentoPDF sont 100 % gratuits, sans limite de fichiers, sans inscription et sans filigrane. Nous pensons que chacun doit avoir accès à des outils PDF simples et puissants, sans barrière payante." + }, + "areFilesSecure": { + "question": "Mes fichiers sont-ils en sécurité ? Où sont-ils traités ?", + "answer": "Vos fichiers sont parfaitement sécurisés car ils ne quittent jamais votre ordinateur. Tous les traitements se font directement dans votre navigateur. Aucun fichier n’est envoyé sur un serveur." + }, + "platforms": { + "question": "Est-ce compatible avec Mac, Windows et mobile ?", + "answer": "Oui ! BentoPDF fonctionne entièrement dans le navigateur et est compatible avec Windows, macOS, Linux, iOS et Android." + }, + "gdprCompliant": { + "question": "BentoPDF est-il conforme au RGPD ?", + "answer": "Oui. Comme tous les traitements sont locaux et qu’aucune donnée n’est collectée ou transmise, vous restez entièrement maître de vos documents." + }, + "dataStorage": { + "question": "Stockez-vous ou suivez-vous mes fichiers ?", + "answer": "Non. Aucun stockage, aucun suivi, aucun historique. Tout disparaît dès que vous fermez la page." + }, + "different": { + "question": "Qu’est-ce qui différencie BentoPDF des autres outils PDF ?", + "answer": "La plupart des outils envoient vos fichiers sur un serveur. BentoPDF traite tout localement dans votre navigateur, pour plus de rapidité, de confidentialité et de tranquillité d’esprit." + }, + "browserBased": { + "question": "Pourquoi le traitement dans le navigateur est-il plus sûr ?", + "answer": "Parce que vos fichiers restent sur votre appareil. Aucun risque de fuite, de piratage ou d’accès non autorisé." + }, + "analytics": { + "question": "Utilisez-vous des cookies ou des outils de suivi ?", + "answer": "Nous respectons votre vie privée. BentoPDF utilise uniquement des statistiques anonymes pour connaître le nombre de visites, sans jamais identifier les utilisateurs." + } + }, + "testimonials": { + "title": "Ce que disent", + "users": "nos utilisateurs", + "say": "" + }, + "support": { + "title": "Vous aimez ce projet ?", + "description": "BentoPDF est un projet passion, créé pour offrir une palette d’outils PDF gratuite, privée et puissante. Si cela vous aide, vous pouvez soutenir son développement. Chaque café compte !", + "buyMeCoffee": "M’offrir un café" + }, + "footer": { + "copyright": "© 2026 BentoPDF. Tous droits réservés.", + "version": "Version", + "company": "Entreprise", + "aboutUs": "À propos", + "faqLink": "FAQ", + "contactUs": "Nous contacter", + "legal": "Mentions légales", + "termsAndConditions": "Conditions générales", + "privacyPolicy": "Politique de confidentialité", + "followUs": "Nous suivre" + }, + "merge": { + "title": "Fusionner des PDF", + "description": "Combinez des fichiers entiers ou sélectionnez des pages spécifiques pour créer un nouveau document.", + "fileMode": "Mode fichiers", + "pageMode": "Mode pages", + "howItWorks": "Fonctionnement :", + "fileModeInstructions": [ + "Cliquez-glissez l’icône pour modifier l’ordre des fichiers.", + "Dans le champ « Pages » de chaque fichier, vous pouvez définir des plages (ex. « 1-3, 5 ») pour ne fusionner que certaines pages.", + "Laissez le champ « Pages » vide pour inclure toutes les pages du fichier." + ], + "pageModeInstructions": [ + "Toutes les pages de vos PDF importés s’affichent ci-dessous.", + "Glissez-déposez simplement les miniatures pour définir l’ordre exact de votre nouveau document." + ], + "mergePdfs": "Fusionner les PDF" + }, + "common": { + "page": "Page", + "pages": "Pages", + "of": "sur", + "download": "Télécharger", + "cancel": "Annuler", + "save": "Enregistrer", + "delete": "Supprimer", + "edit": "Modifier", + "add": "Ajouter", + "remove": "Retirer", + "loading": "Chargement...", + "error": "Erreur", + "success": "Succès", + "file": "Fichier", + "files": "Fichiers" + }, + "about": { + "hero": { + "title": "Nous pensons que les outils PDF doivent être", + "subtitle": "rapides, privés et gratuits.", + "noCompromises": "Sans compromis." + }, + "mission": { + "title": "Notre mission", + "description": "Proposer la palette d’outils PDF la plus complète, tout en respectant votre vie privée et sans jamais demander de paiement. Les outils essentiels doivent être accessibles à tous, partout, sans barrières." + }, + "philosophy": { + "label": "Notre philosophie", + "title": "La confidentialité avant tout. Toujours.", + "description": "À une époque où les données sont devenues une monnaie, nous faisons un choix différent. Tous les traitements des outils BentoPDF sont effectués localement dans votre navigateur. Vos fichiers ne passent jamais par nos serveurs, nous ne voyons jamais vos documents et nous ne suivons pas votre activité. Ce n’est pas une option, c’est notre fondation." + }, + "whyBentopdf": { + "title": "Pourquoi", + "speed": { + "title": "Pensé pour la vitesse", + "description": "Aucune attente liée aux envois ou téléchargements serveur. Grâce au traitement local et aux technologies web modernes comme WebAssembly, nos outils sont extrêmement rapides." + }, + "free": { + "title": "Entièrement gratuit", + "description": "Aucun essai, aucun abonnement, aucun coût caché, aucune fonctionnalité « premium » bloquée. Les outils PDF doivent être un service public, pas un produit de luxe." + }, + "noAccount": { + "title": "Aucun compte requis", + "description": "Utilisez n’importe quel outil immédiatement. Pas d’email, pas de mot de passe, aucune donnée personnelle. Votre flux de travail reste fluide et anonyme." + }, + "openSource": { + "title": "Esprit open source", + "description": "Conçu dans un esprit de transparence. Nous utilisons des bibliothèques open source reconnues comme PDF-lib et PDF.js, et croyons en la force de la communauté." + } + }, + "cta": { + "title": "Prêt à commencer ?", + "description": "Rejoignez des milliers d’utilisateurs qui font confiance à BentoPDF au quotidien. Découvrez la différence qu’apportent la confidentialité et la performance.", + "button": "Explorer tous les outils" + } + }, + "contact": { + "title": "Nous contacter", + "subtitle": "Nous serions ravis d’échanger avec vous. Question, retour ou suggestion de fonctionnalité, n’hésitez pas à nous écrire.", + "email": "Vous pouvez nous contacter directement par email à :" + }, + "licensing": { + "title": "Licences pour", + "subtitle": "Choisissez la licence adaptée à vos besoins." + }, + "multiTool": { + "uploadPdfs": "Importer des PDF", + "upload": "Importer", + "addBlankPage": "Ajouter une page vierge", + "edit": "Modifier :", + "undo": "Annuler", + "redo": "Rétablir", + "reset": "Réinitialiser", + "selection": "Sélection :", + "selectAll": "Tout sélectionner", + "deselectAll": "Tout désélectionner", + "rotate": "Rotation :", + "rotateLeft": "Gauche", + "rotateRight": "Droite", + "transform": "Transformer :", + "duplicate": "Dupliquer", + "split": "Scinder", + "clear": "Effacer :", + "delete": "Supprimer", + "download": "Téléchargement :", + "downloadSelected": "Télécharger la sélection", + "exportPdf": "Exporter en PDF", + "uploadPdfFiles": "Sélectionner des fichiers PDF", + "dragAndDrop": "Glissez-déposez vos fichiers PDF ici ou cliquez pour sélectionner", + "selectFiles": "Sélectionner des fichiers", + "renderingPages": "Rendu des pages...", + "actions": { + "duplicatePage": "Dupliquer cette page", + "deletePage": "Supprimer cette page", + "insertPdf": "Insérer un PDF après cette page", + "toggleSplit": "Activer/désactiver la séparation après cette page" + }, + "pleaseWait": "Veuillez patienter", + "pagesRendering": "Les pages sont en cours de rendu. Veuillez patienter...", + "noPagesSelected": "Aucune page sélectionnée", + "selectOnePage": "Veuillez sélectionner au moins une page à télécharger.", + "noPages": "Aucune page", + "noPagesToExport": "Aucune page à exporter.", + "renderingTitle": "Génération des aperçus", + "errorRendering": "Échec du rendu des miniatures", + "error": "Erreur", + "failedToLoad": "Échec du chargement" + } +} diff --git a/public/locales/fr/tools.json b/public/locales/fr/tools.json new file mode 100644 index 0000000..8f36e7c --- /dev/null +++ b/public/locales/fr/tools.json @@ -0,0 +1,533 @@ +{ + "categories": { + "popularTools": "Outils populaires", + "editAnnotate": "Éditer et annoter", + "convertToPdf": "Convertir en PDF", + "convertFromPdf": "Convertir depuis le PDF", + "organizeManage": "Organiser et gérer", + "optimizeRepair": "Optimiser et réparer", + "securePdf": "Sécuriser les PDF" + }, + "pdfMultiTool": { + "name": "Outil PDF tout-en-un", + "subtitle": "Fusionner, scinder, organiser, supprimer, faire pivoter, ajouter des pages vierges, extraire et dupliquer dans une interface unifiée." + }, + "mergePdf": { + "name": "Fusionner des PDF", + "subtitle": "Assembler plusieurs PDF en un seul fichier, tout en conservant les signets." + }, + "splitPdf": { + "name": "Scinder un PDF", + "subtitle": "Extraire une plage de pages dans un nouveau PDF." + }, + "compressPdf": { + "name": "Compresser un PDF", + "subtitle": "Réduire la taille du fichier PDF.", + "algorithmLabel": "Algorithme de compression", + "condense": "Condensé (recommandé)", + "photon": "Photon (pour les PDF riches en photos)", + "condenseInfo": "Condensé utilise une compression avancée : suppression du superflu, optimisation des images, sous-ensemble des polices. Idéal pour la plupart des PDF.", + "photonInfo": "Photon convertit les pages en images. À utiliser pour les PDF contenant beaucoup de photos ou scannés.", + "photonWarning": "Attention : le texte ne sera plus sélectionnable et les liens ne fonctionneront plus.", + "levelLabel": "Niveau de compression", + "light": "Léger (préserver la qualité)", + "balanced": "Équilibré (recommandé)", + "aggressive": "Agressif (fichiers plus petits)", + "extreme": "Extrême (compression maximale)", + "grayscale": "Convertir en niveaux de gris", + "grayscaleHint": "Réduit la taille du fichier en supprimant les informations de couleur", + "customSettings": "Paramètres personnalisés", + "customSettingsHint": "Affiner les paramètres de compression :", + "outputQuality": "Qualité de sortie", + "resizeImagesTo": "Redimensionner les images à", + "onlyProcessAbove": "Traiter uniquement au-dessus de", + "removeMetadata": "Supprimer les métadonnées", + "subsetFonts": "Sous-ensemble des polices (supprimer les glyphes inutilisés)", + "removeThumbnails": "Supprimer les vignettes intégrées", + "compressButton": "Compresser le PDF" + }, + "pdfEditor": { + "name": "Éditeur PDF", + "subtitle": "Annoter, surligner, masquer, commenter, ajouter des formes ou images, rechercher et afficher des PDF." + }, + "jpgToPdf": { + "name": "JPG vers PDF", + "subtitle": "Créer un PDF à partir d’une ou plusieurs images JPG." + }, + "signPdf": { + "name": "Signer un PDF", + "subtitle": "Dessiner, saisir ou importer votre signature." + }, + "cropPdf": { + "name": "Rogner un PDF", + "subtitle": "Ajuster les marges de chaque page du PDF." + }, + "extractPages": { + "name": "Extraire des pages", + "subtitle": "Enregistrer une sélection de pages dans de nouveaux fichiers." + }, + "duplicateOrganize": { + "name": "Dupliquer et organiser", + "subtitle": "Dupliquer, réorganiser et supprimer des pages." + }, + "deletePages": { + "name": "Supprimer des pages", + "subtitle": "Retirer des pages spécifiques du document." + }, + "editBookmarks": { + "name": "Modifier les signets", + "subtitle": "Ajouter, modifier, importer, supprimer et extraire des signets PDF." + }, + "tableOfContents": { + "name": "Table des matières", + "subtitle": "Générer une table des matières à partir des signets du PDF." + }, + "pageNumbers": { + "name": "Numéros de page", + "subtitle": "Insérer une numérotation dans le document." + }, + "addWatermark": { + "name": "Ajouter un filigrane", + "subtitle": "Apposer un texte ou une image sur les pages du PDF." + }, + "headerFooter": { + "name": "En-tête et pied de page", + "subtitle": "Ajouter du texte en haut et en bas des pages." + }, + "invertColors": { + "name": "Inverser les couleurs", + "subtitle": "Créer une version « mode sombre » du PDF." + }, + "backgroundColor": { + "name": "Couleur de fond", + "subtitle": "Modifier la couleur de fond du PDF." + }, + "changeTextColor": { + "name": "Changer la couleur du texte", + "subtitle": "Modifier la couleur du texte dans le PDF." + }, + "addStamps": { + "name": "Ajouter des tampons", + "subtitle": "Ajouter des tampons image via la barre d’annotations.", + "usernameLabel": "Nom du tampon", + "usernamePlaceholder": "Entrez votre nom (pour les tampons)", + "usernameHint": "Ce nom apparaîtra sur les tampons que vous créez." + }, + "removeAnnotations": { + "name": "Supprimer les annotations", + "subtitle": "Retirer les commentaires, surlignages et liens." + }, + "pdfFormFiller": { + "name": "Remplir un formulaire PDF", + "subtitle": "Remplir des formulaires directement dans le navigateur, y compris les formulaires XFA." + }, + "createPdfForm": { + "name": "Créer un formulaire PDF", + "subtitle": "Créer des formulaires PDF interactifs avec des champs glisser-déposer." + }, + "removeBlankPages": { + "name": "Supprimer les pages blanches", + "subtitle": "Détecter et supprimer automatiquement les pages vides." + }, + "imageToPdf": { + "name": "Images vers PDF", + "subtitle": "Convertir un JPG, PNG, BMP, GIF, TIFF, PNM, PGM, PBM, PPM, PAM, JXR, JPX, JP2, PSD, SVG, HEIC, WebP en PDF." + }, + "pngToPdf": { + "name": "PNG vers PDF", + "subtitle": "Créer un PDF à partir d’une ou plusieurs images PNG." + }, + "webpToPdf": { + "name": "WebP vers PDF", + "subtitle": "Créer un PDF à partir d’une ou plusieurs images WebP." + }, + "svgToPdf": { + "name": "SVG vers PDF", + "subtitle": "Créer un PDF à partir d’une ou plusieurs images SVG." + }, + "bmpToPdf": { + "name": "BMP vers PDF", + "subtitle": "Créer un PDF à partir d’une ou plusieurs images BMP." + }, + "heicToPdf": { + "name": "HEIC vers PDF", + "subtitle": "Créer un PDF à partir d’une ou plusieurs images HEIC." + }, + "tiffToPdf": { + "name": "TIFF vers PDF", + "subtitle": "Créer un PDF à partir d’une ou plusieurs images TIFF." + }, + "textToPdf": { + "name": "Texte vers PDF", + "subtitle": "Convertir un fichier texte en PDF." + }, + "jsonToPdf": { + "name": "JSON vers PDF", + "subtitle": "Convertir des fichiers JSON en PDF." + }, + "pdfToJpg": { + "name": "PDF vers JPG", + "subtitle": "Convertir chaque page du PDF en image JPG." + }, + "pdfToPng": { + "name": "PDF vers PNG", + "subtitle": "Convertir chaque page du PDF en image PNG." + }, + "pdfToWebp": { + "name": "PDF vers WebP", + "subtitle": "Convertir chaque page du PDF en image WebP." + }, + "pdfToBmp": { + "name": "PDF vers BMP", + "subtitle": "Convertir chaque page du PDF en image BMP." + }, + "pdfToTiff": { + "name": "PDF vers TIFF", + "subtitle": "Convertir chaque page du PDF en image TIFF." + }, + "pdfToGreyscale": { + "name": "PDF en niveaux de gris", + "subtitle": "Convertir toutes les couleurs en noir et blanc." + }, + "pdfToJson": { + "name": "PDF vers JSON", + "subtitle": "Convertir des fichiers PDF en JSON." + }, + "ocrPdf": { + "name": "OCR PDF", + "subtitle": "Rendre un PDF consultable et copiable." + }, + "alternateMix": { + "name": "Alterner et mélanger les pages", + "subtitle": "Fusionner des PDF en alternant les pages de chaque fichier, tout en conservant les signets." + }, + "addAttachments": { + "name": "Ajouter des pièces jointes", + "subtitle": "Intégrer un ou plusieurs fichiers dans le PDF." + }, + "extractAttachments": { + "name": "Extraire les pièces jointes", + "subtitle": "Extraire tous les fichiers intégrés des PDF dans une archive ZIP." + }, + "editAttachments": { + "name": "Gérer les pièces jointes", + "subtitle": "Afficher ou supprimer les pièces jointes du PDF." + }, + "dividePages": { + "name": "Diviser les pages", + "subtitle": "Diviser les pages horizontalement ou verticalement." + }, + "addBlankPage": { + "name": "Ajouter une page vierge", + "subtitle": "Insérer une page vide à n’importe quel endroit du PDF." + }, + "reversePages": { + "name": "Inverser l’ordre des pages", + "subtitle": "Renverser l’ordre de toutes les pages du document." + }, + "rotatePdf": { + "name": "Faire pivoter un PDF", + "subtitle": "Tourner les pages par incréments de 90°." + }, + "rotateCustom": { + "name": "Rotation par angle personnalisé", + "subtitle": "Faire pivoter les pages selon un angle personnalisé." + }, + "nUpPdf": { + "name": "PDF N-up", + "subtitle": "Afficher plusieurs pages sur une seule feuille." + }, + "combineToSinglePage": { + "name": "Combiner en une seule page", + "subtitle": "Assembler toutes les pages en un défilement continu." + }, + "viewMetadata": { + "name": "Afficher les métadonnées", + "subtitle": "Consulter les propriétés internes du PDF." + }, + "editMetadata": { + "name": "Modifier les métadonnées", + "subtitle": "Changer l’auteur, le titre et autres propriétés." + }, + "pdfsToZip": { + "name": "PDF vers ZIP", + "subtitle": "Regrouper plusieurs fichiers PDF dans une archive ZIP." + }, + "comparePdfs": { + "name": "Comparer des PDF", + "subtitle": "Comparer deux PDF côte à côte." + }, + "posterizePdf": { + "name": "Posteriser un PDF", + "subtitle": "Découper une grande page en plusieurs pages plus petites." + }, + "fixPageSize": { + "name": "Uniformiser la taille des pages", + "subtitle": "Standardiser toutes les pages à un format identique." + }, + "linearizePdf": { + "name": "Optimiser pour le web", + "subtitle": "Optimiser le PDF pour un affichage rapide en ligne." + }, + "pageDimensions": { + "name": "Dimensions des pages", + "subtitle": "Analyser la taille, l’orientation et les unités des pages." + }, + "removeRestrictions": { + "name": "Supprimer les restrictions", + "subtitle": "Supprimer les protections par mot de passe et restrictions de sécurité des PDF signés." + }, + "repairPdf": { + "name": "Réparer un PDF", + "subtitle": "Récupérer les données de fichiers PDF corrompus ou endommagés." + }, + "encryptPdf": { + "name": "Chiffrer un PDF", + "subtitle": "Protéger le PDF en ajoutant un mot de passe." + }, + "sanitizePdf": { + "name": "Nettoyer un PDF", + "subtitle": "Supprimer les métadonnées, annotations, scripts et autres éléments sensibles." + }, + "decryptPdf": { + "name": "Déverrouiller un PDF", + "subtitle": "Supprimer la protection par mot de passe." + }, + "flattenPdf": { + "name": "Aplatir le PDF", + "subtitle": "Rendre les champs de formulaire et annotations non modifiables." + }, + "removeMetadata": { + "name": "Supprimer les métadonnées", + "subtitle": "Effacer les données cachées du PDF." + }, + "changePermissions": { + "name": "Modifier les autorisations", + "subtitle": "Définir ou modifier les permissions utilisateur du PDF." + }, + "odtToPdf": { + "name": "ODT vers PDF", + "subtitle": "Convertir des fichiers OpenDocument Text au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers ODT", + "convertButton": "Convertir en PDF" + }, + "csvToPdf": { + "name": "CSV vers PDF", + "subtitle": "Convertir des fichiers tableur CSV au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers CSV", + "convertButton": "Convertir en PDF" + }, + "rtfToPdf": { + "name": "RTF vers PDF", + "subtitle": "Convertir des documents Rich Text Format en PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers RTF", + "convertButton": "Convertir en PDF" + }, + "wordToPdf": { + "name": "Word vers PDF", + "subtitle": "Convertir des documents Word (DOCX, DOC, ODT, RTF) au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers DOCX, DOC, ODT, RTF", + "convertButton": "Convertir en PDF" + }, + "excelToPdf": { + "name": "Excel vers PDF", + "subtitle": "Convertir des feuilles de calcul Excel (XLSX, XLS, ODS, CSV) au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers XLSX, XLS, ODS, CSV", + "convertButton": "Convertir en PDF" + }, + "powerpointToPdf": { + "name": "PowerPoint vers PDF", + "subtitle": "Convertir des présentations PowerPoint (PPTX, PPT, ODP) au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers PPTX, PPT, ODP", + "convertButton": "Convertir en PDF" + }, + "markdownToPdf": { + "name": "Markdown vers PDF", + "subtitle": "Écrire ou coller du Markdown et l’exporter en PDF avec une mise en forme soignée.", + "paneMarkdown": "Markdown", + "panePreview": "Aperçu", + "btnUpload": "Téléverser", + "btnSyncScroll": "Synchroniser le défilement", + "btnSettings": "Paramètres", + "btnExportPdf": "Exporter en PDF", + "settingsTitle": "Paramètres Markdown", + "settingsPreset": "Préréglage", + "presetDefault": "Par défaut (type GFM)", + "presetCommonmark": "CommonMark (strict)", + "presetZero": "Minimal (aucune fonctionnalité)", + "settingsOptions": "Options Markdown", + "optAllowHtml": "Autoriser les balises HTML", + "optBreaks": "Convertir les retours à la ligne en
", + "optLinkify": "Convertir automatiquement les URL en liens", + "optTypographer": "Typographie (guillemets intelligents, etc.)" + }, + "pdfBooklet": { + "name": "Livret PDF", + "subtitle": "Réorganiser les pages pour l’impression recto verso en livret. Pliez et agrafez pour créer un livret.", + "howItWorks": "Fonctionnement :", + "step1": "Téléversez un fichier PDF.", + "step2": "Les pages seront réorganisées dans l’ordre du livret.", + "step3": "Imprimez en recto verso, retournement sur le bord court, pliez et agrafez.", + "paperSize": "Format du papier", + "orientation": "Orientation", + "portrait": "Portrait", + "landscape": "Paysage", + "pagesPerSheet": "Pages par feuille", + "createBooklet": "Créer le livret", + "processing": "Traitement...", + "pageCount": "Le nombre de pages sera complété au multiple de 4 si nécessaire." + }, + "xpsToPdf": { + "name": "XPS vers PDF", + "subtitle": "Convertir des documents XPS/OXPS au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers XPS, OXPS", + "convertButton": "Convertir en PDF" + }, + "mobiToPdf": { + "name": "MOBI vers PDF", + "subtitle": "Convertir des livres numériques MOBI au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers MOBI", + "convertButton": "Convertir en PDF" + }, + "epubToPdf": { + "name": "EPUB vers PDF", + "subtitle": "Convertir des livres numériques EPUB au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers EPUB", + "convertButton": "Convertir en PDF" + }, + "fb2ToPdf": { + "name": "FB2 vers PDF", + "subtitle": "Convertir des livres numériques FictionBook (FB2) au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers FB2", + "convertButton": "Convertir en PDF" + }, + "cbzToPdf": { + "name": "CBZ vers PDF", + "subtitle": "Convertir des archives de bandes dessinées (CBZ/CBR) au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers CBZ, CBR", + "convertButton": "Convertir en PDF" + }, + "wpdToPdf": { + "name": "WPD vers PDF", + "subtitle": "Convertir des documents WordPerfect (WPD) au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers WPD", + "convertButton": "Convertir en PDF" + }, + "wpsToPdf": { + "name": "WPS vers PDF", + "subtitle": "Convertir des documents WPS Office au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers WPS", + "convertButton": "Convertir en PDF" + }, + "xmlToPdf": { + "name": "XML vers PDF", + "subtitle": "Convertir des documents XML au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers XML", + "convertButton": "Convertir en PDF" + }, + "pagesToPdf": { + "name": "Pages vers PDF", + "subtitle": "Convertir des documents Apple Pages au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers Pages", + "convertButton": "Convertir en PDF" + }, + "odgToPdf": { + "name": "ODG vers PDF", + "subtitle": "Convertir des fichiers OpenDocument Graphics (ODG) au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers ODG", + "convertButton": "Convertir en PDF" + }, + "odsToPdf": { + "name": "ODS vers PDF", + "subtitle": "Convertir des fichiers OpenDocument Spreadsheet (ODS) au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers ODS", + "convertButton": "Convertir en PDF" + }, + "odpToPdf": { + "name": "ODP vers PDF", + "subtitle": "Convertir des fichiers OpenDocument Presentation (ODP) au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers ODP", + "convertButton": "Convertir en PDF" + }, + "pubToPdf": { + "name": "PUB vers PDF", + "subtitle": "Convertir des fichiers Microsoft Publisher (PUB) au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers PUB", + "convertButton": "Convertir en PDF" + }, + "vsdToPdf": { + "name": "VSD vers PDF", + "subtitle": "Convertir des fichiers Microsoft Visio (VSD, VSDX) au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers VSD, VSDX", + "convertButton": "Convertir en PDF" + }, + "psdToPdf": { + "name": "PSD vers PDF", + "subtitle": "Convertir des fichiers Adobe Photoshop (PSD) au format PDF. Prend en charge plusieurs fichiers.", + "acceptedFormats": "Fichiers PSD", + "convertButton": "Convertir en PDF" + }, + "pdfToSvg": { + "name": "PDF vers SVG", + "subtitle": "Convertir chaque page d’un fichier PDF en graphique vectoriel évolutif (SVG) pour une qualité parfaite à toutes les tailles." + }, + "extractTables": { + "name": "Extraire les tableaux PDF", + "subtitle": "Extraire les tableaux des fichiers PDF et les exporter en CSV, JSON ou Markdown." + }, + "pdfToCsv": { + "name": "PDF vers CSV", + "subtitle": "Extraire les tableaux d’un PDF et les convertir au format CSV." + }, + "pdfToExcel": { + "name": "PDF vers Excel", + "subtitle": "Extraire les tableaux d’un PDF et les convertir au format Excel (XLSX)." + }, + "pdfToText": { + "name": "PDF vers texte", + "subtitle": "Extraire le texte des fichiers PDF et l’enregistrer en texte brut (.txt). Prend en charge plusieurs fichiers.", + "note": "Cet outil fonctionne UNIQUEMENT avec des PDF créés numériquement. Pour les documents scannés ou les PDF basés sur des images, utilisez plutôt notre outil OCR PDF.", + "convertButton": "Extraire le texte" + }, + "digitalSignPdf": { + "name": "Signature numérique PDF", + "pageTitle": "Signature numérique PDF - Ajouter une signature cryptographique | BentoPDF", + "subtitle": "Ajouter une signature numérique cryptographique à votre PDF à l’aide de certificats X.509. Prend en charge les formats PKCS#12 (.pfx, .p12) et PEM. Votre clé privée ne quitte jamais votre navigateur.", + "certificateSection": "Certificat", + "uploadCert": "Téléverser un certificat (.pfx, .p12)", + "certPassword": "Mot de passe du certificat", + "certPasswordPlaceholder": "Saisissez le mot de passe du certificat", + "certInfo": "Informations du certificat", + "certSubject": "Sujet", + "certIssuer": "Émetteur", + "certValidity": "Validité", + "signatureDetails": "Détails de la signature (facultatif)", + "reason": "Motif", + "reasonPlaceholder": "ex. : J’approuve ce document", + "location": "Lieu", + "locationPlaceholder": "ex. : Paris, France", + "contactInfo": "Coordonnées", + "contactPlaceholder": "ex. : email@exemple.com", + "applySignature": "Appliquer la signature numérique", + "successMessage": "PDF signé avec succès ! La signature peut être vérifiée dans n’importe quel lecteur PDF." + }, + "validateSignaturePdf": { + "name": "Valider la signature PDF", + "pageTitle": "Valider la signature PDF - Vérifier les signatures numériques | BentoPDF", + "subtitle": "Vérifier les signatures numériques de vos fichiers PDF. Contrôlez la validité du certificat, consultez les informations du signataire et confirmez l’intégrité du document. Tout le traitement s’effectue dans votre navigateur." + }, + "emailToPdf": { + "name": "Email vers PDF", + "subtitle": "Convertir des fichiers email (EML, MSG) au format PDF. Prend en charge les exports Outlook et les formats email standards.", + "acceptedFormats": "Fichiers EML, MSG", + "convertButton": "Convertir en PDF" + }, + "fontToOutline": { + "name": "Polices en contours", + "subtitle": "Convertir toutes les polices en contours vectoriels pour un rendu cohérent sur tous les appareils." + }, + "deskewPdf": { + "name": "Redresser un PDF", + "subtitle": "Redresser automatiquement les pages scannées inclinées à l’aide d’OpenCV." + } +} diff --git a/public/locales/id/common.json b/public/locales/id/common.json new file mode 100644 index 0000000..a07d616 --- /dev/null +++ b/public/locales/id/common.json @@ -0,0 +1,323 @@ +{ + "nav": { + "home": "Beranda", + "about": "Tentang", + "contact": "Kontak", + "licensing": "Lisensi", + "allTools": "Semua Alat", + "openMainMenu": "Buka menu utama", + "language": "Bahasa" + }, + "donation": { + "message": "Suka BentoPDF? Bantu kami menjaganya tetap gratis dan sumber terbuka!", + "button": "Donasi" + }, + "hero": { + "title": " ", + "pdfToolkit": "Toolkit PDF", + "builtForPrivacy": "yang dibuat untuk privasi", + "noSignups": "Tidak Ada Pendaftaran", + "unlimitedUse": "Penggunaan Tak Terbatas", + "worksOffline": "Bekerja Offline ", + "startUsing": "Mulai Menggunakan Sekarang" + }, + "usedBy": { + "title": "Digunakan oleh perusahaan dan orang yang bekerja di" + }, + "features": { + "title": "Mengapa memilih", + "bentoPdf": "BentoPDF?", + "noSignup": { + "title": "Tidak Ada Pendaftaran", + "description": "Mulai seketika, tanpa akun atau email." + }, + "noUploads": { + "title": "Tidak Ada Unggahan", + "description": "100% di sisi klien, file Anda tidak pernah meninggalkan perangkat Anda." + }, + "foreverFree": { + "title": "Gratis Selamanya", + "description": "Semua alat, tidak ada uji coba, tidak ada biaya berlangganan." + }, + "noLimits": { + "title": "Tanpa Batas", + "description": "Gunakan sebanyak yang Anda inginkan, tanpa batas tersembunyi." + }, + "batchProcessing": { + "title": "Pemrosesan Kelompok", + "description": "Tangani PDF tak terbatas dalam satu kali jalan." + }, + "lightningFast": { + "title": "Sangat Cepat", + "description": "Proses PDF secara instan, tanpa menunggu atau penundaan." + } + }, + "tools": { + "title": "Mulai dengan", + "toolsLabel": "Alat", + "subtitle": "Klik alat untuk membuka pengunggah file", + "searchPlaceholder": "Cari alat (contoh, 'pisah', 'organisir'...)", + "backToTools": "Kembali ke Alat", + "firstLoadNotice": "Pemuatan pertama memerlukan waktu sebentar karena kami mengunduh mesin konversi kami. Setelah itu, semua pemuatan akan instan." + }, + "upload": { + "clickToSelect": "Klik untuk memilih file", + "orDragAndDrop": "atau seret dan jatuhkan", + "pdfOrImages": "PDF atau Gambar", + "filesNeverLeave": "File Anda tidak pernah meninggalkan perangkat Anda.", + "addMore": "Tambah Lebih Banyak File", + "clearAll": "Hapus Semua" + }, + "loader": { + "processing": "Memproses..." + }, + "alert": { + "title": "Peringatan", + "ok": "OK" + }, + "preview": { + "title": "Pratinjau Dokumen", + "downloadAsPdf": "Unduh sebagai PDF", + "close": "Tutup" + }, + "settings": { + "title": "Pengaturan", + "shortcuts": "Pintasan", + "preferences": "Preferensi", + "displayPreferences": "Preferensi Tampilan", + "searchShortcuts": "Cari pintasan...", + "shortcutsInfo": "Tekan dan tahan tombol untuk mengatur pintasan. Perubahan disimpan otomatis.", + "shortcutsWarning": "⚠️ Hindari pintasan browser umum (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N dll.) karena mungkin tidak bekerja dengan baik.", + "import": "Impor", + "export": "Ekspor", + "resetToDefaults": "Atur Ulang ke Default", + "fullWidthMode": "Mode Lebar Penuh", + "fullWidthDescription": "Gunakan lebar layar penuh untuk semua alat, bukan wadah yang dipusatkan", + "settingsAutoSaved": "Pengaturan disimpan secara otomatis", + "clickToSet": "Klik untuk mengatur", + "pressKeys": "Tekan tombol...", + "warnings": { + "alreadyInUse": "Pintasan Sudah Digunakan", + "assignedTo": "sudah ditugaskan ke:", + "chooseDifferent": "Silakan pilih pintasan yang berbeda.", + "reserved": "Peringatan Pintasan Cadangan", + "commonlyUsed": "biasanya digunakan untuk:", + "unreliable": "Pintasan ini mungkin tidak berfungsi dengan andal atau mungkin bertentangan dengan perilaku browser/sistem.", + "useAnyway": "Apakah Anda ingin menggunakannya saja?", + "resetTitle": "Atur Ulang Pintasan", + "resetMessage": "Apakah Anda yakin ingin mengatur ulang semua pintasan ke default?

Tindakan ini tidak dapat dibatalkan.", + "importSuccessTitle": "Impor Berhasil", + "importSuccessMessage": "Pintasan berhasil diimpor!", + "importFailTitle": "Impor Gagal", + "importFailMessage": "Gagal mengimpor pintasan. Format file tidak valid." + } + }, + "warning": { + "title": "Peringatan", + "cancel": "Batal", + "proceed": "Lanjutkan" + }, + "compliance": { + "title": "Data Anda tidak pernah meninggalkan perangkat Anda", + "weKeep": "Kami menjaga", + "yourInfoSafe": "informasi Anda aman", + "byFollowingStandards": "dengan mengikuti standar keamanan global.", + "processingLocal": "Semua pemrosesan terjadi secara lokal di perangkat Anda.", + "gdpr": { + "title": "Kepatuhan GDPR", + "description": "Melindungi data pribadi dan privasi individu dalam Uni Eropa." + }, + "ccpa": { + "title": "Kepatuhan CCPA", + "description": "Memberikan hak kepada penduduk California atas bagaimana informasi pribadi mereka dikumpulkan, digunakan, dan dibagikan." + }, + "hipaa": { + "title": "Kepatuhan HIPAA", + "description": "Menetapkan perlindungan untuk menangani informasi kesehatan sensitif dalam sistem perawatan kesehatan Amerika Serikat." + } + }, + "faq": { + "title": "Pertanyaan yang Sering Diajukan", + "questions": "Pertanyaan", + "isFree": { + "question": "Apakah BentoPDF benar-benar gratis?", + "answer": "Ya, tentu saja. Semua alat di BentoPDF 100% gratis digunakan, tanpa batas file, tanpa pendaftaran, dan tanpa watermark. Kami percaya semua orang berhak mendapatkan akses ke alat PDF sederhana dan kuat tanpa paywall." + }, + "areFilesSecure": { + "question": "Apakah file saya aman? Di mana file diproses?", + "answer": "File Anda sangat aman karena tidak pernah meninggalkan komputer Anda. Semua pemrosesan terjadi langsung di browser web Anda (sisi klien). Kami tidak pernah mengunggah file Anda ke server, sehingga Anda mempertahankan privasi dan kontrol lengkap atas dokumen Anda." + }, + "platforms": { + "question": "Apakah ini bekerja di Mac, Windows, dan Mobile?", + "answer": "Ya! Karena BentoPDF berjalan sepenuhnya di browser Anda, ini bekerja di sistem operasi apa pun dengan browser web modern, termasuk Windows, macOS, Linux, iOS, dan Android." + }, + "gdprCompliant": { + "question": "Apakah BentoPDF patuh GDPR?", + "answer": "Ya. BentoPDF sepenuhnya patuh GDPR. Karena semua pemrosesan file terjadi secara lokal di browser Anda dan kami tidak pernah mengumpulkan atau mentransmisikan file Anda ke server mana pun, kami tidak memiliki akses ke data Anda. Ini memastikan Anda selalu mengontrol dokumen Anda." + }, + "dataStorage": { + "question": "Apakah Anda menyimpan atau melacak file saya?", + "answer": "Tidak. Kami tidak pernah menyimpan, melacak, atau mencatat file Anda. Semua yang Anda lakukan di BentoPDF terjadi di memori browser Anda dan hilang setelah Anda menutup halaman. Tidak ada unggahan, tidak ada log riwayat, dan tidak ada server yang terlibat." + }, + "different": { + "question": "Apa yang membuat BentoPDF berbeda dari alat PDF lainnya?", + "answer": "Kebanyakan alat PDF mengunggah file Anda ke server untuk diproses. BentoPDF nggak pernah begitu. Kami pakai teknologi web modern dan aman buat memproses file Anda langsung di browser Anda. Ini berarti performa lebih cepat, privasi lebih kuat, dan ketenangan pikiran." + }, + "browserBased": { + "question": "Bagaimana pemrosesan berbasis browser menjaga keamanan saya?", + "answer": "Dengan berjalan sepenuhnya di dalam browser Anda, BentoPDF memastikan file Anda tidak pernah meninggalkan perangkat Anda. Ini menghilangkan risiko peretasan server, pelanggaran data, atau akses tidak sah. File Anda tetap milik Anda—selalu." + }, + "analytics": { + "question": "Apakah Anda menggunakan cookie atau analitik untuk melacak saya?", + "answer": "Kami peduli dengan privasi Anda. BentoPDF tidak melacak informasi pribadi. Kami menggunakan Simple Analytics hanya untuk melihat jumlah kunjungan anonim. Ini berarti kami dapat mengetahui berapa banyak pengguna yang mengunjungi situs kami, tetapi kami tidak pernah tahu siapa Anda. Simple Analytics sepenuhnya patuh GDPR dan menghormati privasi Anda." + } + }, + "testimonials": { + "title": "Apa Kata", + "users": "Pengguna", + "say": "Kami" + }, + "support": { + "title": "Suka Karya Saya?", + "description": "BentoPDF adalah proyek yang dibuat dengan sepenuh hati, untuk menyediakan toolkit PDF gratis, pribadi, dan kuat untuk semua orang. Kalau kamu merasa ini berguna, pertimbangkan untuk mendukung pengembangannya. Setiap secangkir kopi membantu!", + "buyMeCoffee": "Beli Kopi untuk Saya" + }, + "footer": { + "copyright": "© 2026 BentoPDF. Hak cipta dilindungi.", + "version": "Versi", + "company": "Perusahaan", + "aboutUs": "Tentang Kami", + "faqLink": "FAQ", + "contactUs": "Hubungi Kami", + "legal": "Hukum", + "termsAndConditions": "Syarat dan Ketentuan", + "privacyPolicy": "Kebijakan Privasi", + "followUs": "Ikuti Kami" + }, + "merge": { + "title": "Gabung PDF", + "description": "Gabungkan file utuh, atau pilih halaman tertentu untuk digabungkan ke dalam dokumen baru.", + "fileMode": "Mode File", + "pageMode": "Mode Halaman", + "howItWorks": "Cara kerjanya:", + "fileModeInstructions": [ + "Klik dan seret ikon untuk mengubah urutan file.", + "Di kotak \"Halaman\" untuk setiap file, Anda dapat menentukan rentang (misalnya, \"1-3, 5\") untuk menggabungkan hanya halaman tersebut.", + "Biarkan kotak \"Halaman\" kosong untuk menyertakan semua halaman dari file tersebut." + ], + "pageModeInstructions": [ + "Semua halaman dari PDF yang Anda unggah ditampilkan di bawah.", + "Cukup seret dan jatuhkan thumbnail halaman satu per satu untuk membuat urutan yang tepat sesuai keinginan kamu untuk file baru." + ], + "mergePdfs": "Gabung PDF" + }, + "common": { + "page": "Halaman", + "pages": "Halaman", + "of": "dari", + "download": "Unduh", + "cancel": "Batal", + "save": "Simpan", + "delete": "Hapus", + "edit": "Edit", + "add": "Tambah", + "remove": "Hapus", + "loading": "Memuat...", + "error": "Kesalahan", + "success": "Berhasil", + "file": "File", + "files": "File" + }, + "about": { + "hero": { + "title": "Kami percaya alat PDF harus", + "subtitle": "cepat, pribadi, dan gratis.", + "noCompromises": "Tidak ada kompromi." + }, + "mission": { + "title": "Misi Kami", + "description": "Untuk menyediakan toolbox PDF paling komprehensif yang menghormati privasi Anda dan tidak pernah meminta pembayaran. Kami percaya alat dokumen penting harus dapat diakses oleh semua orang, di mana saja, tanpa hambatan." + }, + "philosophy": { + "label": "Filosofi Inti Kami", + "title": "Privasi Yang Utama. Selalu.", + "description": "Di era di mana data adalah komoditas, kami mengambil pendekatan berbeda. Semua pemrosesan untuk alat Bentopdf terjadi secara lokal di browser Anda. Ini berarti file Anda tidak pernah menyentuh server kami, kami tidak pernah melihat dokumen Anda, dan kami tidak melacak apa yang Anda lakukan. Dokumen Anda tetap utuh dan privat secara tegas. Ini bukan hanya fitur; ini adalah fondasi kami." + }, + "whyBentopdf": { + "title": "Mengapa", + "speed": { + "title": "Dibuat untuk Kecepatan", + "description": "Tidak ada menunggu unggahan atau unduhan ke server. Dengan memproses file langsung di browser Anda menggunakan teknologi web modern seperti WebAssembly, kami menawarkan kecepatan yang tak tertandingi untuk semua alat kami." + }, + "free": { + "title": "Sepenuhnya Gratis", + "description": "Tidak ada uji coba, tidak ada langganan, tidak ada biaya tersembunyi, dan tidak ada fitur \"premium\" yang ditahan sebagai sandera. Kami percaya alat PDF yang kuat harus menjadi utilitas publik, bukan pusat keuntungan." + }, + "noAccount": { + "title": "Tidak Perlu Akun", + "description": "Langsung mulai pakai alat apa saja. Kami tidak perlu email Anda, kata sandi, atau informasi pribadi apa pun. Alur kerja Anda harus lancar dan anonim." + }, + "openSource": { + "title": "Semangat Sumber Terbuka", + "description": "Dibangun dengan transparansi sebagai prioritas. Kami manfaatkan pustaka open-source yang luar biasa seperti PDF-lib dan PDF.js, dan percaya pada upaya yang didorong komunitas untuk membuat alat-alat kuat bisa diakses semua orang." + } + }, + "cta": { + "title": "Siap untuk memulai?", + "description": "Bergabunglah dengan ribuan pengguna yang percaya Bentopdf untuk kebutuhan dokumen harian mereka. Rasakan bedanya privasi dan performa yang ditawarkan.", + "button": "Jelajahi Semua Alat" + } + }, + "contact": { + "title": "Hubungi Kami", + "subtitle": "Kami senang mendengar dari Anda. Apakah Anda memiliki pertanyaan, umpan balik, atau permintaan fitur, jangan ragu untuk menghubungi kami.", + "email": "Anda dapat menghubungi kami secara langsung melalui email di:" + }, + "licensing": { + "title": "Lisensi untuk", + "subtitle": "Pilih lisensi yang sesuai dengan kebutuhan Anda." + }, + "multiTool": { + "uploadPdfs": "Unggah PDF", + "upload": "Unggah", + "addBlankPage": "Tambah Halaman Kosong", + "edit": "Edit:", + "undo": "Undo", + "redo": "Redo", + "reset": "Atur Ulang", + "selection": "Pilihan:", + "selectAll": "Pilih Semua", + "deselectAll": "Batalkan Pilih Semua", + "rotate": "Putar:", + "rotateLeft": "Kiri", + "rotateRight": "Kanan", + "transform": "Transform:", + "duplicate": "Duplikat", + "split": "Pisah", + "clear": "Hapus:", + "delete": "Hapus", + "download": "Unduh:", + "downloadSelected": "Unduh yang Dipilih", + "exportPdf": "Ekspor PDF", + "uploadPdfFiles": "Pilih File PDF", + "dragAndDrop": "Seret dan jatuhkan file PDF di sini, atau klik untuk memilih", + "selectFiles": "Pilih File", + "renderingPages": "Merender halaman...", + "actions": { + "duplicatePage": "Duplikat halaman ini", + "deletePage": "Hapus halaman ini", + "insertPdf": "Sisipkan PDF setelah halaman ini", + "toggleSplit": "Alihkan pisah setelah halaman ini" + }, + "pleaseWait": "Harap Tunggu", + "pagesRendering": "Halaman masih dirender. Harap tunggu...", + "noPagesSelected": "Tidak Ada Halaman yang Dipilih", + "selectOnePage": "Silakan pilih setidaknya satu halaman untuk diunduh.", + "noPages": "Tidak Ada Halaman", + "noPagesToExport": "Tidak ada halaman untuk diekspor.", + "renderingTitle": "Merender pratinjau halaman", + "errorRendering": "Gagal merender thumbnail halaman", + "error": "Kesalahan", + "failedToLoad": "Gagal memuat" + } +} diff --git a/public/locales/id/tools.json b/public/locales/id/tools.json new file mode 100644 index 0000000..95e9bb6 --- /dev/null +++ b/public/locales/id/tools.json @@ -0,0 +1,533 @@ +{ + "categories": { + "popularTools": "Alat Populer", + "editAnnotate": "Edit & Anotasi", + "convertToPdf": "Konversi ke PDF", + "convertFromPdf": "Konversi dari PDF", + "organizeManage": "Atur & Kelola", + "optimizeRepair": "Optimalkan & Perbaiki", + "securePdf": "Amankan PDF" + }, + "pdfMultiTool": { + "name": "Alat Multi PDF", + "subtitle": "Gabung, Pisah, Atur, Hapus, Putar, Tambah Halaman Kosong, Ekstrak dan Duplikat dalam antarmuka terpadu." + }, + "mergePdf": { + "name": "Gabung PDF", + "subtitle": "Gabungkan beberapa PDF menjadi satu file. Mempertahankan Bookmark." + }, + "splitPdf": { + "name": "Pisah PDF", + "subtitle": "Ekstrak rentang halaman ke PDF baru." + }, + "compressPdf": { + "name": "Kompres PDF", + "subtitle": "Kurangi ukuran file PDF Anda.", + "algorithmLabel": "Algoritma Kompresi", + "condense": "Kondensasi (Direkomendasikan)", + "photon": "Photon (Untuk PDF yang penuh Foto)", + "condenseInfo": "Kondensasi menggunakan kompresi lanjutan: menghapus bobot mati, mengoptimalkan gambar, subset font. Terbaik untuk sebagian besar PDF.", + "photonInfo": "Photon mengkonversi halaman ke gambar. Gunakan untuk PDF penuh foto/terpindai.", + "photonWarning": "Peringatan: Teks akan menjadi tidak dapat dipilih dan tautan akan berhenti berfungsi.", + "levelLabel": "Tingkat Kompresi", + "light": "Ringan (Pertahankan Kualitas)", + "balanced": "Seimbang (Direkomendasikan)", + "aggressive": "Agresif (File Lebih Kecil)", + "extreme": "Ekstrem (Kompresi Maksimum)", + "grayscale": "Konversi ke Grayscale", + "grayscaleHint": "Mengurangi ukuran file dengan menghapus informasi warna", + "customSettings": "Pengaturan Kustom", + "customSettingsHint": "Sesuaikan parameter kompresi:", + "outputQuality": "Kualitas Output", + "resizeImagesTo": "Ubah Ukuran Gambar Ke", + "onlyProcessAbove": "Hanya Proses Di Atas", + "removeMetadata": "Hapus metadata", + "subsetFonts": "Subset font (hapus glyph yang tidak digunakan)", + "removeThumbnails": "Hapus thumbnail tersemat", + "compressButton": "Kompres PDF" + }, + "pdfEditor": { + "name": "Editor PDF", + "subtitle": "Anotasi, sorot, redaksi, komentar, tambah bentuk/gambar, cari, dan lihat PDF." + }, + "jpgToPdf": { + "name": "JPG ke PDF", + "subtitle": "Buat PDF dari gambar JPG, JPEG, dan JPEG2000 (JP2/JPX)." + }, + "signPdf": { + "name": "Tanda Tangan PDF", + "subtitle": "Gambar, ketik, atau unggah tanda tangan Anda." + }, + "cropPdf": { + "name": "Potong PDF", + "subtitle": "Potong margin setiap halaman di PDF Anda." + }, + "extractPages": { + "name": "Ekstrak Halaman", + "subtitle": "Simpan pilihan halaman sebagai file baru." + }, + "duplicateOrganize": { + "name": "Duplikat & Atur", + "subtitle": "Duplikat, susun ulang, dan hapus halaman." + }, + "deletePages": { + "name": "Hapus Halaman", + "subtitle": "Hapus halaman tertentu dari dokumen Anda." + }, + "editBookmarks": { + "name": "Edit Bookmark", + "subtitle": "Tambah, edit, impor, hapus dan ekstrak bookmark PDF." + }, + "tableOfContents": { + "name": "Daftar Isi", + "subtitle": "Hasilkan halaman daftar isi dari bookmark PDF." + }, + "pageNumbers": { + "name": "Nomor Halaman", + "subtitle": "Sisipkan nomor halaman ke dokumen Anda." + }, + "addWatermark": { + "name": "Tambah Watermark", + "subtitle": "Cap teks atau gambar di atas halaman PDF Anda." + }, + "headerFooter": { + "name": "Header & Footer", + "subtitle": "Tambah teks ke bagian atas dan bawah halaman." + }, + "invertColors": { + "name": "Balik Warna", + "subtitle": "Buat versi \"mode gelap\" dari PDF Anda." + }, + "backgroundColor": { + "name": "Warna Latar Belakang", + "subtitle": "Ubah warna latar belakang PDF Anda." + }, + "changeTextColor": { + "name": "Ubah Warna Teks", + "subtitle": "Ubah warna teks di PDF Anda." + }, + "addStamps": { + "name": "Tambah Stempel", + "subtitle": "Tambah stempel gambar ke PDF Anda menggunakan toolbar anotasi.", + "usernameLabel": "Nama Pengguna Stempel", + "usernamePlaceholder": "Masukkan nama Anda (untuk stempel)", + "usernameHint": "Nama ini akan muncul pada stempel yang Anda buat." + }, + "removeAnnotations": { + "name": "Hapus Anotasi", + "subtitle": "Hapus komentar, sorotan, dan tautan." + }, + "pdfFormFiller": { + "name": "Pengisi Formulir PDF", + "subtitle": "Isi formulir langsung di browser. Juga mendukung formulir XFA." + }, + "createPdfForm": { + "name": "Buat Formulir PDF", + "subtitle": "Buat formulir PDF yang dapat diisi dengan bidang teks drag-and-drop." + }, + "removeBlankPages": { + "name": "Hapus Halaman Kosong", + "subtitle": "Deteksi dan hapus halaman kosong secara otomatis." + }, + "imageToPdf": { + "name": "Gambar ke PDF", + "subtitle": "Konversi JPG, PNG, BMP, GIF, TIFF, PNM, PGM, PBM, PPM, PAM, JXR, JPX, JP2, PSD, SVG, HEIC, WebP ke PDF." + }, + "pngToPdf": { + "name": "PNG ke PDF", + "subtitle": "Buat PDF dari satu atau lebih gambar PNG." + }, + "webpToPdf": { + "name": "WebP ke PDF", + "subtitle": "Buat PDF dari satu atau lebih gambar WebP." + }, + "svgToPdf": { + "name": "SVG ke PDF", + "subtitle": "Buat PDF dari satu atau lebih gambar SVG." + }, + "bmpToPdf": { + "name": "BMP ke PDF", + "subtitle": "Buat PDF dari satu atau lebih gambar BMP." + }, + "heicToPdf": { + "name": "HEIC ke PDF", + "subtitle": "Buat PDF dari satu atau lebih gambar HEIC." + }, + "tiffToPdf": { + "name": "TIFF ke PDF", + "subtitle": "Buat PDF dari satu atau lebih gambar TIFF." + }, + "textToPdf": { + "name": "Teks ke PDF", + "subtitle": "Konversi file teks biasa menjadi PDF." + }, + "jsonToPdf": { + "name": "JSON ke PDF", + "subtitle": "Konversi file JSON ke format PDF." + }, + "pdfToJpg": { + "name": "PDF ke JPG", + "subtitle": "Konversi setiap halaman PDF menjadi gambar JPG." + }, + "pdfToPng": { + "name": "PDF ke PNG", + "subtitle": "Konversi setiap halaman PDF menjadi gambar PNG." + }, + "pdfToWebp": { + "name": "PDF ke WebP", + "subtitle": "Konversi setiap halaman PDF menjadi gambar WebP." + }, + "pdfToBmp": { + "name": "PDF ke BMP", + "subtitle": "Konversi setiap halaman PDF menjadi gambar BMP." + }, + "pdfToTiff": { + "name": "PDF ke TIFF", + "subtitle": "Konversi setiap halaman PDF menjadi gambar TIFF." + }, + "pdfToGreyscale": { + "name": "PDF ke Skala Abu-abu", + "subtitle": "Konversi semua warna ke hitam dan putih." + }, + "pdfToJson": { + "name": "PDF ke JSON", + "subtitle": "Konversi file PDF ke format JSON." + }, + "ocrPdf": { + "name": "OCR PDF", + "subtitle": "Buat PDF dapat dicari dan disalin." + }, + "alternateMix": { + "name": "Alternatif & Campur Halaman", + "subtitle": "Gabung PDF dengan menggantikan halaman dari setiap PDF. Mempertahankan Bookmark." + }, + "addAttachments": { + "name": "Tambah Lampiran", + "subtitle": "Sematkan satu atau lebih file ke PDF Anda." + }, + "extractAttachments": { + "name": "Ekstrak Lampiran", + "subtitle": "Ekstrak semua file tersemat dari PDF sebagai ZIP." + }, + "editAttachments": { + "name": "Edit Lampiran", + "subtitle": "Lihat atau hapus lampiran di PDF Anda." + }, + "dividePages": { + "name": "Bagi Halaman", + "subtitle": "Bagi halaman secara horizontal atau vertikal." + }, + "addBlankPage": { + "name": "Tambah Halaman Kosong", + "subtitle": "Sisipkan halaman kosong di mana saja di PDF Anda." + }, + "reversePages": { + "name": "Balik Halaman", + "subtitle": "Balik urutan semua halaman di dokumen Anda." + }, + "rotatePdf": { + "name": "Putar PDF", + "subtitle": "Putar halaman dalam kenaikan 90 derajat." + }, + "rotateCustom": { + "name": "Putar dengan Derajat Kustom", + "subtitle": "Putar halaman dengan sudut kustom apa pun." + }, + "nUpPdf": { + "name": "N-Up PDF", + "subtitle": "Susun beberapa halaman ke satu lembar." + }, + "combineToSinglePage": { + "name": "Gabung ke Halaman Tunggal", + "subtitle": "Jahit semua halaman menjadi satu gulungan berkelanjutan." + }, + "viewMetadata": { + "name": "Lihat Metadata", + "subtitle": "Periksa properti tersembunyi PDF Anda." + }, + "editMetadata": { + "name": "Edit Metadata", + "subtitle": "Ubah penulis, judul, dan properti lainnya." + }, + "pdfsToZip": { + "name": "PDF ke ZIP", + "subtitle": "Paket beberapa file PDF ke arsip ZIP." + }, + "comparePdfs": { + "name": "Bandingkan PDF", + "subtitle": "Bandingkan dua PDF berdampingan." + }, + "posterizePdf": { + "name": "Posterisasi PDF", + "subtitle": "Pisah halaman besar menjadi beberapa halaman lebih kecil." + }, + "fixPageSize": { + "name": "Perbaiki Ukuran Halaman", + "subtitle": "Standarkan semua halaman ke ukuran seragam." + }, + "linearizePdf": { + "name": "Linierisasi PDF", + "subtitle": "Optimalkan PDF untuk tampilan web cepat." + }, + "pageDimensions": { + "name": "Dimensi Halaman", + "subtitle": "Analisis ukuran halaman, orientasi, dan unit." + }, + "removeRestrictions": { + "name": "Hapus Pembatasan", + "subtitle": "Hapus perlindungan kata sandi dan pembatasan keamanan yang terkait dengan file PDF yang ditandatangani secara digital." + }, + "repairPdf": { + "name": "Perbaiki PDF", + "subtitle": "Pulihkan data dari file PDF yang rusak atau rusak." + }, + "encryptPdf": { + "name": "Enkripsi PDF", + "subtitle": "Kunci PDF Anda dengan menambahkan kata sandi." + }, + "sanitizePdf": { + "name": "Sanitasi PDF", + "subtitle": "Hapus metadata, anotasi, skrip, dan lainnya." + }, + "decryptPdf": { + "name": "Dekripsi PDF", + "subtitle": "Buka kunci PDF dengan menghapus perlindungan kata sandi." + }, + "flattenPdf": { + "name": "Ratakan PDF", + "subtitle": "Buat bidang formulir dan anotasi tidak dapat diedit." + }, + "removeMetadata": { + "name": "Hapus Metadata", + "subtitle": "Hapus data tersembunyi dari PDF Anda." + }, + "changePermissions": { + "name": "Ubah Izin", + "subtitle": "Atur atau ubah izin pengguna pada PDF." + }, + "odtToPdf": { + "name": "ODT ke PDF", + "subtitle": "Konversi file OpenDocument Text ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File ODT", + "convertButton": "Konversi ke PDF" + }, + "csvToPdf": { + "name": "CSV ke PDF", + "subtitle": "Konversi file spreadsheet CSV ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File CSV", + "convertButton": "Konversi ke PDF" + }, + "rtfToPdf": { + "name": "RTF ke PDF", + "subtitle": "Konversi dokumen Rich Text Format ke PDF. Mendukung beberapa file.", + "acceptedFormats": "File RTF", + "convertButton": "Konversi ke PDF" + }, + "wordToPdf": { + "name": "Word ke PDF", + "subtitle": "Konversi dokumen Word (DOCX, DOC, ODT, RTF) ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File DOCX, DOC, ODT, RTF", + "convertButton": "Konversi ke PDF" + }, + "excelToPdf": { + "name": "Excel ke PDF", + "subtitle": "Konversi spreadsheet Excel (XLSX, XLS, ODS, CSV) ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File XLSX, XLS, ODS, CSV", + "convertButton": "Konversi ke PDF" + }, + "powerpointToPdf": { + "name": "PowerPoint ke PDF", + "subtitle": "Konversi presentasi PowerPoint (PPTX, PPT, ODP) ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File PPTX, PPT, ODP", + "convertButton": "Konversi ke PDF" + }, + "markdownToPdf": { + "name": "Markdown ke PDF", + "subtitle": "Tulis atau tempel Markdown dan ekspor sebagai PDF yang diformat dengan indah.", + "paneMarkdown": "Markdown", + "panePreview": "Pratinjau", + "btnUpload": "Unggah", + "btnSyncScroll": "Sinkron Gulir", + "btnSettings": "Pengaturan", + "btnExportPdf": "Ekspor PDF", + "settingsTitle": "Pengaturan Markdown", + "settingsPreset": "Preset", + "presetDefault": "Default (seperti GFM)", + "presetCommonmark": "CommonMark (ketat)", + "presetZero": "Minimal (tanpa fitur)", + "settingsOptions": "Opsi Markdown", + "optAllowHtml": "Izinkan tag HTML", + "optBreaks": "Konversi baris baru ke
", + "optLinkify": "Konversi otomatis URL ke tautan", + "optTypographer": "Typographer (kutipan cerdas, dll.)" + }, + "pdfBooklet": { + "name": "Buku Kecil PDF", + "subtitle": "Susun ulang halaman untuk pencetakan buku kecil dua sisi. Lipat dan jahit untuk membuat buku kecil.", + "howItWorks": "Cara kerjanya:", + "step1": "Unggah file PDF.", + "step2": "Halaman akan disusun ulang dalam urutan buku kecil.", + "step3": "Cetak dua sisi, balik di tepi pendek, lipat dan jahit.", + "paperSize": "Ukuran Kertas", + "orientation": "Orientasi", + "portrait": "Potret", + "landscape": "Lanskap", + "pagesPerSheet": "Halaman per Lembar", + "createBooklet": "Buat Buku Kecil", + "processing": "Memproses...", + "pageCount": "Jumlah halaman akan diisi ke kelipatan 4 jika diperlukan." + }, + "xpsToPdf": { + "name": "XPS ke PDF", + "subtitle": "Konversi dokumen XPS/OXPS ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File XPS, OXPS", + "convertButton": "Konversi ke PDF" + }, + "mobiToPdf": { + "name": "MOBI ke PDF", + "subtitle": "Konversi e-book MOBI ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File MOBI", + "convertButton": "Konversi ke PDF" + }, + "epubToPdf": { + "name": "EPUB ke PDF", + "subtitle": "Konversi e-book EPUB ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File EPUB", + "convertButton": "Konversi ke PDF" + }, + "fb2ToPdf": { + "name": "FB2 ke PDF", + "subtitle": "Konversi e-book FictionBook (FB2) ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File FB2", + "convertButton": "Konversi ke PDF" + }, + "cbzToPdf": { + "name": "CBZ ke PDF", + "subtitle": "Konversi arsip buku komik (CBZ/CBR) ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File CBZ, CBR", + "convertButton": "Konversi ke PDF" + }, + "wpdToPdf": { + "name": "WPD ke PDF", + "subtitle": "Konversi dokumen WordPerfect (WPD) ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File WPD", + "convertButton": "Konversi ke PDF" + }, + "wpsToPdf": { + "name": "WPS ke PDF", + "subtitle": "Konversi dokumen WPS Office ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File WPS", + "convertButton": "Konversi ke PDF" + }, + "xmlToPdf": { + "name": "XML ke PDF", + "subtitle": "Konversi dokumen XML ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File XML", + "convertButton": "Konversi ke PDF" + }, + "pagesToPdf": { + "name": "Pages ke PDF", + "subtitle": "Konversi dokumen Apple Pages ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File Pages", + "convertButton": "Konversi ke PDF" + }, + "odgToPdf": { + "name": "ODG ke PDF", + "subtitle": "Konversi file OpenDocument Graphics (ODG) ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File ODG", + "convertButton": "Konversi ke PDF" + }, + "odsToPdf": { + "name": "ODS ke PDF", + "subtitle": "Konversi file OpenDocument Spreadsheet (ODS) ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File ODS", + "convertButton": "Konversi ke PDF" + }, + "odpToPdf": { + "name": "ODP ke PDF", + "subtitle": "Konversi file OpenDocument Presentation (ODP) ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File ODP", + "convertButton": "Konversi ke PDF" + }, + "pubToPdf": { + "name": "PUB ke PDF", + "subtitle": "Konversi file Microsoft Publisher (PUB) ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File PUB", + "convertButton": "Konversi ke PDF" + }, + "vsdToPdf": { + "name": "VSD ke PDF", + "subtitle": "Konversi file Microsoft Visio (VSD, VSDX) ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File VSD, VSDX", + "convertButton": "Konversi ke PDF" + }, + "psdToPdf": { + "name": "PSD ke PDF", + "subtitle": "Konversi file Adobe Photoshop (PSD) ke format PDF. Mendukung beberapa file.", + "acceptedFormats": "File PSD", + "convertButton": "Konversi ke PDF" + }, + "pdfToSvg": { + "name": "PDF ke SVG", + "subtitle": "Konversi setiap halaman file PDF menjadi grafik vektor skalabel (SVG) untuk kualitas sempurna di ukuran apa pun." + }, + "extractTables": { + "name": "Ekstrak Tabel PDF", + "subtitle": "Ekstrak tabel dari file PDF dan ekspor sebagai CSV, JSON, atau Markdown." + }, + "pdfToCsv": { + "name": "PDF ke CSV", + "subtitle": "Ekstrak tabel dari PDF dan konversi ke format CSV." + }, + "pdfToExcel": { + "name": "PDF ke Excel", + "subtitle": "Ekstrak tabel dari PDF dan konversi ke format Excel (XLSX)." + }, + "pdfToText": { + "name": "PDF ke Teks", + "subtitle": "Ekstrak teks dari file PDF dan simpan sebagai teks biasa (.txt). Mendukung beberapa file.", + "note": "Alat ini bekerja HANYA dengan PDF yang dibuat secara digital. Untuk dokumen terpindai atau PDF berbasis gambar, gunakan alat OCR PDF kami sebagai gantinya.", + "convertButton": "Ekstrak Teks" + }, + "digitalSignPdf": { + "name": "Tanda Tangan Digital PDF", + "pageTitle": "Tanda Tangan Digital PDF - Tambah Tanda Tangan Kriptografi | BentoPDF", + "subtitle": "Tambah tanda tangan digital kriptografi ke PDF Anda menggunakan sertifikat X.509. Mendukung format PKCS#12 (.pfx, .p12) dan PEM. Kunci pribadi Anda tidak pernah meninggalkan browser Anda.", + "certificateSection": "Sertifikat", + "uploadCert": "Unggah sertifikat (.pfx, .p12)", + "certPassword": "Kata Sandi Sertifikat", + "certPasswordPlaceholder": "Masukkan kata sandi sertifikat", + "certInfo": "Informasi Sertifikat", + "certSubject": "Subjek", + "certIssuer": "Penerbit", + "certValidity": "Valid", + "signatureDetails": "Detail Tanda Tangan (Opsional)", + "reason": "Alasan", + "reasonPlaceholder": "misalnya, Saya menyetujui dokumen ini", + "location": "Lokasi", + "locationPlaceholder": "misalnya, Jakarta, Indonesia", + "contactInfo": "Info Kontak", + "contactPlaceholder": "misalnya, email@contoh.com", + "applySignature": "Terapkan Tanda Tangan Digital", + "successMessage": "PDF berhasil ditandatangani! Tanda tangan dapat diverifikasi di pembaca PDF apa pun." + }, + "validateSignaturePdf": { + "name": "Validasi Tanda Tangan PDF", + "pageTitle": "Validasi Tanda Tangan PDF - Verifikasi Tanda Tangan Digital | BentoPDF", + "subtitle": "Verifikasi tanda tangan digital di file PDF Anda. Periksa validitas sertifikat, lihat detail penandatangan, dan konfirmasi integritas dokumen. Semua pemrosesan terjadi di browser Anda." + }, + "emailToPdf": { + "name": "Email ke PDF", + "subtitle": "Konversi file email (EML, MSG) ke format PDF. Mendukung ekspor Outlook dan format email standar.", + "acceptedFormats": "File EML, MSG", + "convertButton": "Konversi ke PDF" + }, + "fontToOutline": { + "name": "Font ke Garis Tepi", + "subtitle": "Konversi semua font ke garis tepi vektor untuk tampilan konsisten di semua perangkat." + }, + "deskewPdf": { + "name": "Luruskan PDF", + "subtitle": "Otomatis meluruskan halaman hasil pindai yang miring menggunakan OpenCV." + } +} diff --git a/public/locales/it/common.json b/public/locales/it/common.json new file mode 100644 index 0000000..c7d7b81 --- /dev/null +++ b/public/locales/it/common.json @@ -0,0 +1,323 @@ +{ + "nav": { + "home": "Home", + "about": "Chi siamo", + "contact": "Contatti", + "licensing": "Licenze", + "allTools": "Tutti gli strumenti", + "openMainMenu": "Apri il menu principale", + "language": "Lingua" + }, + "donation": { + "message": "Ti piace BentoPDF? Aiutaci a mantenerlo gratuito e open source!", + "button": "Dona" + }, + "hero": { + "title": "Il", + "pdfToolkit": "kit di strumenti PDF", + "builtForPrivacy": "pensato per la privacy", + "noSignups": "Nessuna registrazione", + "unlimitedUse": "Uso illimitato", + "worksOffline": "Funziona offline", + "startUsing": "Inizia a usarlo ora" + }, + "usedBy": { + "title": "Usato da aziende e persone che lavorano in" + }, + "features": { + "title": "Perché scegliere", + "bentoPdf": "BentoPDF?", + "noSignup": { + "title": "Nessuna registrazione", + "description": "Inizia subito, senza account né email." + }, + "noUploads": { + "title": "Nessun caricamento", + "description": "100% client-side, i tuoi file non lasciano mai il dispositivo." + }, + "foreverFree": { + "title": "Sempre gratis", + "description": "Tutti gli strumenti, nessuna prova, nessun paywall." + }, + "noLimits": { + "title": "Senza limiti", + "description": "Usalo quanto vuoi, senza limiti nascosti." + }, + "batchProcessing": { + "title": "Elaborazione in batch", + "description": "Gestisci un numero illimitato di PDF in un'unica operazione." + }, + "lightningFast": { + "title": "Fulmineo", + "description": "Elabora i PDF istantaneamente, senza attese o ritardi." + } + }, + "tools": { + "title": "Inizia con", + "toolsLabel": "Strumenti", + "subtitle": "Clicca su uno strumento per aprire il caricatore di file", + "searchPlaceholder": "Cerca uno strumento (es. \"split\", \"organizza\"...)", + "backToTools": "Torna agli strumenti", + "firstLoadNotice": "Il primo caricamento richiede qualche istante mentre scarichiamo il motore di conversione. Dopo di ciò, tutti i caricamenti saranno immediati." + }, + "upload": { + "clickToSelect": "Clicca per selezionare un file", + "orDragAndDrop": "oppure trascina e rilascia", + "pdfOrImages": "PDF o immagini", + "filesNeverLeave": "I tuoi file non lasciano mai il tuo dispositivo.", + "addMore": "Aggiungi altri file", + "clearAll": "Svuota tutto" + }, + "loader": { + "processing": "Elaborazione..." + }, + "alert": { + "title": "Avviso", + "ok": "OK" + }, + "preview": { + "title": "Anteprima documento", + "downloadAsPdf": "Scarica come PDF", + "close": "Chiudi" + }, + "settings": { + "title": "Impostazioni", + "shortcuts": "Scorciatoie", + "preferences": "Preferenze", + "displayPreferences": "Preferenze di visualizzazione", + "searchShortcuts": "Cerca scorciatoie...", + "shortcutsInfo": "Premi e tieni premuti i tasti per impostare una scorciatoia. Le modifiche vengono salvate automaticamente.", + "shortcutsWarning": "⚠️ Evita le scorciatoie comuni del browser (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N ecc.) perché potrebbero non funzionare in modo affidabile.", + "import": "Importa", + "export": "Esporta", + "resetToDefaults": "Reimposta ai valori predefiniti", + "fullWidthMode": "Modalità a tutta larghezza", + "fullWidthDescription": "Usa l'intera larghezza dello schermo per tutti gli strumenti invece di un contenitore centrato", + "settingsAutoSaved": "Le impostazioni vengono salvate automaticamente", + "clickToSet": "Clicca per impostare", + "pressKeys": "Premi i tasti...", + "warnings": { + "alreadyInUse": "Scorciatoia già in uso", + "assignedTo": "è già assegnata a:", + "chooseDifferent": "Per favore scegli una scorciatoia diversa.", + "reserved": "Avviso: scorciatoia riservata", + "commonlyUsed": "è comunemente usata per:", + "unreliable": "Questa scorciatoia potrebbe non funzionare in modo affidabile o potrebbe avere conflitti con il comportamento del browser/sistema.", + "useAnyway": "Vuoi usarla comunque?", + "resetTitle": "Reimposta scorciatoie", + "resetMessage": "Sei sicuro di voler reimpostare tutte le scorciatoie ai valori predefiniti?

Questa azione non può essere annullata.", + "importSuccessTitle": "Importazione riuscita", + "importSuccessMessage": "Scorciatoie importate con successo!", + "importFailTitle": "Importazione fallita", + "importFailMessage": "Impossibile importare le scorciatoie. Formato file non valido." + } + }, + "warning": { + "title": "Avviso", + "cancel": "Annulla", + "proceed": "Procedi" + }, + "compliance": { + "title": "I tuoi dati non lasciano mai il tuo dispositivo", + "weKeep": "Manteniamo", + "yourInfoSafe": "le tue informazioni al sicuro", + "byFollowingStandards": "seguendo gli standard di sicurezza globali.", + "processingLocal": "Tutte le elaborazioni avvengono localmente sul tuo dispositivo.", + "gdpr": { + "title": "Conformità GDPR", + "description": "Protegge i dati personali e la privacy delle persone all'interno dell'Unione Europea." + }, + "ccpa": { + "title": "Conformità CCPA", + "description": "Conferisce ai residenti della California diritti su come le loro informazioni personali vengono raccolte, usate e condivise." + }, + "hipaa": { + "title": "Conformità HIPAA", + "description": "Stabilisce salvaguardie per la gestione delle informazioni sanitarie sensibili nel sistema sanitario degli Stati Uniti." + } + }, + "faq": { + "title": "Domande", + "questions": "Frequenti", + "isFree": { + "question": "BentoPDF è davvero gratuito?", + "answer": "Sì, assolutamente. Tutti gli strumenti su BentoPDF sono gratuiti al 100%, senza limiti di file, senza registrazioni e senza filigrane. Crediamo che tutti debbano poter accedere a strumenti PDF semplici e potenti senza barriere a pagamento." + }, + "areFilesSecure": { + "question": "I miei file sono sicuri? Dove vengono elaborati?", + "answer": "I tuoi file sono il più sicuri possibile perché non lasciano mai il tuo computer. Tutte le elaborazioni avvengono direttamente nel tuo browser (lato client). Non carichiamo mai i tuoi file su un server, quindi mantieni la privacy completa e il controllo sui tuoi documenti." + }, + "platforms": { + "question": "Funziona su Mac, Windows e dispositivi mobili?", + "answer": "Sì! Poiché BentoPDF viene eseguito interamente nel tuo browser, funziona su qualsiasi sistema operativo con un browser moderno, inclusi Windows, macOS, Linux, iOS e Android." + }, + "gdprCompliant": { + "question": "BentoPDF è conforme al GDPR?", + "answer": "Sì. BentoPDF è pienamente conforme al GDPR. Poiché tutte le elaborazioni avvengono localmente nel tuo browser e non raccogliamo né trasmettiamo i tuoi file a server, non abbiamo accesso ai tuoi dati. Questo garantisce che tu abbia sempre il controllo sui tuoi documenti." + }, + "dataStorage": { + "question": "Conservate o tracciate i miei file?", + "answer": "No. Non conserviamo, tracciamo né registriamo i tuoi file. Tutto ciò che fai su BentoPDF avviene nella memoria del tuo browser e scompare quando chiudi la pagina. Non ci sono upload, né log di cronologia, né server coinvolti." + }, + "different": { + "question": "Cosa rende BentoPDF diverso dagli altri strumenti PDF?", + "answer": "La maggior parte degli strumenti PDF carica i file su un server per l'elaborazione. BentoPDF non lo fa mai. Utilizziamo tecnologie web moderne e sicure per elaborare i tuoi file direttamente nel browser. Questo significa prestazioni più rapide, maggiore privacy e tranquillità." + }, + "browserBased": { + "question": "In che modo l'elaborazione nel browser mi protegge?", + "answer": "Eseguendosi interamente nel browser, BentoPDF garantisce che i tuoi file non lascino mai il tuo dispositivo. Questo elimina i rischi di attacchi ai server, violazioni dei dati o accessi non autorizzati. I tuoi file restano sempre tuoi." + }, + "analytics": { + "question": "Usate cookie o analytics per tracciarmi?", + "answer": "Ci teniamo alla tua privacy. BentoPDF non traccia informazioni personali. Usiamo Simple Analytics solo per visualizzare conteggi di visite anonime. Questo significa che possiamo sapere quante persone visitano il sito, ma non chi sei. Simple Analytics è pienamente conforme al GDPR e rispetta la tua privacy." + } + }, + "testimonials": { + "title": "Cosa", + "users": "dicono i nostri", + "say": "utenti" + }, + "support": { + "title": "Ti piace il mio lavoro?", + "description": "BentoPDF è un progetto nato per passione, creato per offrire una cassetta degli attrezzi PDF gratuita, privata e potente per tutti. Se lo trovi utile, considera di supportarne lo sviluppo. Ogni caffè aiuta!", + "buyMeCoffee": "Offrimi un caffè" + }, + "footer": { + "copyright": "© 2026 BentoPDF. Tutti i diritti riservati.", + "version": "Versione", + "company": "Azienda", + "aboutUs": "Chi siamo", + "faqLink": "FAQ", + "contactUs": "Contattaci", + "legal": "Legale", + "termsAndConditions": "Termini e condizioni", + "privacyPolicy": "Informativa sulla privacy", + "followUs": "Seguici" + }, + "merge": { + "title": "Unisci PDF", + "description": "Combina file interi, oppure seleziona pagine specifiche da unire in un nuovo documento.", + "fileMode": "Modalità file", + "pageMode": "Modalità pagina", + "howItWorks": "Come funziona:", + "fileModeInstructions": [ + "Clicca e trascina l'icona per cambiare l'ordine dei file.", + "Nella casella \"Pagine\" per ogni file, puoi specificare intervalli (es., \"1-3, 5\") per unire solo quelle pagine.", + "Lascia vuota la casella \"Pagine\" per includere tutte le pagine di quel file." + ], + "pageModeInstructions": [ + "Tutte le pagine dei tuoi PDF caricati vengono mostrate qui sotto.", + "Trascina e rilascia le miniature delle singole pagine per creare l'ordine esatto che desideri per il nuovo file." + ], + "mergePdfs": "Unisci PDF" + }, + "common": { + "page": "Pagina", + "pages": "Pagine", + "of": "di", + "download": "Scarica", + "cancel": "Annulla", + "save": "Salva", + "delete": "Elimina", + "edit": "Modifica", + "add": "Aggiungi", + "remove": "Rimuovi", + "loading": "Caricamento...", + "error": "Errore", + "success": "Successo", + "file": "File", + "files": "File" + }, + "about": { + "hero": { + "title": "Crediamo che gli strumenti PDF debbano essere", + "subtitle": "veloci, privati e gratuiti.", + "noCompromises": "Nessun compromesso." + }, + "mission": { + "title": "La nostra missione", + "description": "Fornire la cassetta degli attrezzi per PDF più completa che rispetti la tua privacy e non richieda mai pagamenti. Crediamo che gli strumenti essenziali per i documenti debbano essere accessibili a tutti, ovunque, senza barriere." + }, + "philosophy": { + "label": "La nostra filosofia fondamentale", + "title": "Prima la privacy. Sempre.", + "description": "In un'epoca in cui i dati sono una merce, adottiamo un approccio diverso. Tutte le elaborazioni per gli strumenti BentoPDF avvengono localmente nel tuo browser. Questo significa che i tuoi file non toccano mai i nostri server, non vediamo i tuoi documenti e non tracciamo ciò che fai. I tuoi documenti restano completamente e inequivocabilmente privati. Non è solo una funzionalità; è il nostro fondamento." + }, + "whyBentopdf": { + "title": "Perché BentoPDF", + "speed": { + "title": "Progettato per la velocità", + "description": "Nessuna attesa per upload o download verso un server. Elaborando i file direttamente nel browser con tecnologie web moderne come WebAssembly, offriamo una velocità impareggiabile per tutti i nostri strumenti." + }, + "free": { + "title": "Completamente gratuito", + "description": "Niente prove, niente abbonamenti, nessun costo nascosto e nessuna funzione \"premium\" tenuta in ostaggio. Crediamo che potenti strumenti PDF debbano essere un servizio pubblico, non una fonte di profitto." + }, + "noAccount": { + "title": "Nessun account richiesto", + "description": "Inizia a usare qualsiasi strumento immediatamente. Non abbiamo bisogno della tua email, di una password o di informazioni personali. Il tuo flusso di lavoro deve essere semplice e anonimo." + }, + "openSource": { + "title": "Spirito open source", + "description": "Costruito con trasparenza. Sfruttiamo librerie open‑source incredibili come PDF-lib e PDF.js, e crediamo nello sforzo della community per rendere strumenti potenti accessibili a tutti." + } + }, + "cta": { + "title": "Pronto per iniziare?", + "description": "Unisciti a migliaia di utenti che si affidano a BentoPDF per le loro esigenze quotidiane sui documenti. Sperimenta la differenza che privacy e prestazioni possono offrire.", + "button": "Esplora tutti gli strumenti" + } + }, + "contact": { + "title": "Contattaci", + "subtitle": "Ci farebbe piacere sentirti. Che tu abbia una domanda, un feedback o una richiesta di funzionalità, non esitare a contattarci.", + "email": "Puoi contattarci direttamente via email a:" + }, + "licensing": { + "title": "Licenze per", + "subtitle": "Scegli la licenza che si adatta alle tue esigenze." + }, + "multiTool": { + "uploadPdfs": "Carica PDF", + "upload": "Carica", + "addBlankPage": "Aggiungi pagina vuota", + "edit": "Modifica:", + "undo": "Annulla", + "redo": "Ripeti", + "reset": "Reimposta", + "selection": "Selezione:", + "selectAll": "Seleziona tutto", + "deselectAll": "Deseleziona tutto", + "rotate": "Ruota:", + "rotateLeft": "Sinistra", + "rotateRight": "Destra", + "transform": "Trasforma:", + "duplicate": "Duplica", + "split": "Dividi", + "clear": "Svuota:", + "delete": "Elimina", + "download": "Scarica:", + "downloadSelected": "Scarica selezionati", + "exportPdf": "Esporta PDF", + "uploadPdfFiles": "Seleziona file PDF", + "dragAndDrop": "Trascina e rilascia i file PDF qui, oppure clicca per selezionare", + "selectFiles": "Seleziona file", + "renderingPages": "Generazione anteprime pagine...", + "actions": { + "duplicatePage": "Duplica questa pagina", + "deletePage": "Elimina questa pagina", + "insertPdf": "Inserisci PDF dopo questa pagina", + "toggleSplit": "Attiva la divisione dopo questa pagina" + }, + "pleaseWait": "Attendere...", + "pagesRendering": "Le pagine sono ancora in fase di generazione. Attendere...", + "noPagesSelected": "Nessuna pagina selezionata", + "selectOnePage": "Seleziona almeno una pagina da scaricare.", + "noPages": "Nessuna pagina", + "noPagesToExport": "Non ci sono pagine da esportare.", + "renderingTitle": "Generazione anteprime delle pagine", + "errorRendering": "Impossibile generare le miniature delle pagine", + "error": "Errore", + "failedToLoad": "Caricamento fallito" + } +} diff --git a/public/locales/it/tools.json b/public/locales/it/tools.json new file mode 100644 index 0000000..0caf98e --- /dev/null +++ b/public/locales/it/tools.json @@ -0,0 +1,533 @@ +{ + "categories": { + "popularTools": "Strumenti popolari", + "editAnnotate": "Modifica e Annota", + "convertToPdf": "Converti in PDF", + "convertFromPdf": "Converti da PDF", + "organizeManage": "Organizza e Gestisci", + "optimizeRepair": "Ottimizza e Ripara", + "securePdf": "Proteggi PDF" + }, + "pdfMultiTool": { + "name": "Strumento PDF multifunzione", + "subtitle": "Unisci, dividi, organizza, elimina, ruota, aggiungi pagine vuote, estrai e duplica in un'interfaccia unificata." + }, + "mergePdf": { + "name": "Unisci PDF", + "subtitle": "Unisci più PDF in un unico file. Conserva i segnalibri." + }, + "splitPdf": { + "name": "Dividi PDF", + "subtitle": "Estrai un insieme di pagine in un nuovo PDF." + }, + "compressPdf": { + "name": "Comprimi PDF", + "subtitle": "Riduci le dimensioni del tuo PDF.", + "algorithmLabel": "Algoritmo di compressione", + "condense": "Condensa (Consigliato)", + "photon": "Photon (Per PDF con molte foto)", + "condenseInfo": "Condensa usa la compressione avanzata: rimuove peso inutile, ottimizza le immagini, riduce i font. Migliore per la maggior parte dei PDF.", + "photonInfo": "Photon converte le pagine in immagini. Usalo per PDF con molte foto o scannerizzati.", + "photonWarning": "Attenzione: il testo non sarà selezionabile e i link smetteranno di funzionare.", + "levelLabel": "Livello di compressione", + "light": "Leggero (Preserva qualità)", + "balanced": "Bilanciato (Consigliato)", + "aggressive": "Aggressivo (File più piccoli)", + "extreme": "Estremo (Compressione massima)", + "grayscale": "Converti in scala di grigi", + "grayscaleHint": "Riduce le dimensioni rimuovendo le informazioni di colore", + "customSettings": "Impostazioni personalizzate", + "customSettingsHint": "Affina i parametri di compressione:", + "outputQuality": "Qualità di output", + "resizeImagesTo": "Ridimensiona le immagini a", + "onlyProcessAbove": "Elabora solo sopra", + "removeMetadata": "Rimuovi metadati", + "subsetFonts": "Riduci i font (rimuovi glifi non usati)", + "removeThumbnails": "Rimuovi miniature incorporate", + "compressButton": "Comprimi PDF" + }, + "pdfEditor": { + "name": "Editor PDF", + "subtitle": "Annota, evidenzia, redigi, commenta, aggiungi forme/immagini, cerca e visualizza PDF." + }, + "jpgToPdf": { + "name": "JPG in PDF", + "subtitle": "Crea un PDF da immagini JPG, JPEG e JPEG2000 (JP2/JPX)." + }, + "signPdf": { + "name": "Firma PDF", + "subtitle": "Disegna, digita o carica la tua firma." + }, + "cropPdf": { + "name": "Ritaglia PDF", + "subtitle": "Rimuovi i margini di ogni pagina del tuo PDF." + }, + "extractPages": { + "name": "Estrai Pagine", + "subtitle": "Salva una selezione di pagine come nuovi file." + }, + "duplicateOrganize": { + "name": "Duplica e Organizza", + "subtitle": "Duplica, riordina ed elimina pagine." + }, + "deletePages": { + "name": "Elimina Pagine", + "subtitle": "Rimuovi pagine specifiche dal tuo documento." + }, + "editBookmarks": { + "name": "Modifica Segnalibri", + "subtitle": "Aggiungi, modifica, importa, elimina ed estrai segnalibri PDF." + }, + "tableOfContents": { + "name": "Indice", + "subtitle": "Genera una pagina di indice dai segnalibri del PDF." + }, + "pageNumbers": { + "name": "Numeri di Pagina", + "subtitle": "Inserisci i numeri di pagina nel tuo documento." + }, + "addWatermark": { + "name": "Aggiungi Filigrana", + "subtitle": "Applica testo o un'immagine sulle pagine del tuo PDF." + }, + "headerFooter": { + "name": "Intestazione e Piè di Pagina", + "subtitle": "Aggiungi testo nella parte superiore e inferiore delle pagine." + }, + "invertColors": { + "name": "Inverti Colori", + "subtitle": "Crea una versione \"modalità scura\" del tuo PDF." + }, + "backgroundColor": { + "name": "Colore di Sfondo", + "subtitle": "Cambia il colore di sfondo del tuo PDF." + }, + "changeTextColor": { + "name": "Cambia Colore Testo", + "subtitle": "Cambia il colore del testo nel tuo PDF." + }, + "addStamps": { + "name": "Aggiungi Timbri", + "subtitle": "Aggiungi timbri immagine al tuo PDF usando la barra degli strumenti di annotazione.", + "usernameLabel": "Nome sul timbro", + "usernamePlaceholder": "Inserisci il tuo nome (per i timbri)", + "usernameHint": "Questo nome apparirà sui timbri che crei." + }, + "removeAnnotations": { + "name": "Rimuovi Annotazioni", + "subtitle": "Rimuovi commenti, evidenziazioni e link." + }, + "pdfFormFiller": { + "name": "Compilatore Moduli PDF", + "subtitle": "Compila i moduli direttamente nel browser. Supporta anche i moduli XFA." + }, + "createPdfForm": { + "name": "Crea Modulo PDF", + "subtitle": "Crea moduli PDF compilabili con campi di testo drag-and-drop." + }, + "removeBlankPages": { + "name": "Rimuovi Pagine Vuote", + "subtitle": "Rileva e elimina automaticamente le pagine vuote." + }, + "imageToPdf": { + "name": "Immagini in PDF", + "subtitle": "Converti JPG, PNG, BMP, GIF, TIFF, PNM, PGM, PBM, PPM, PAM, JXR, JPX, JP2, PSD, SVG, HEIC, WebP in PDF." + }, + "pngToPdf": { + "name": "PNG in PDF", + "subtitle": "Crea un PDF da una o più immagini PNG." + }, + "webpToPdf": { + "name": "WebP in PDF", + "subtitle": "Crea un PDF da una o più immagini WebP." + }, + "svgToPdf": { + "name": "SVG in PDF", + "subtitle": "Crea un PDF da una o più immagini SVG." + }, + "bmpToPdf": { + "name": "BMP in PDF", + "subtitle": "Crea un PDF da una o più immagini BMP." + }, + "heicToPdf": { + "name": "HEIC in PDF", + "subtitle": "Crea un PDF da una o più immagini HEIC." + }, + "tiffToPdf": { + "name": "TIFF in PDF", + "subtitle": "Crea un PDF da una o più immagini TIFF." + }, + "textToPdf": { + "name": "Testo in PDF", + "subtitle": "Converti un file di testo semplice in un PDF." + }, + "jsonToPdf": { + "name": "JSON in PDF", + "subtitle": "Converti file JSON in formato PDF." + }, + "pdfToJpg": { + "name": "PDF in JPG", + "subtitle": "Converti ogni pagina del PDF in un'immagine JPG." + }, + "pdfToPng": { + "name": "PDF in PNG", + "subtitle": "Converti ogni pagina del PDF in un'immagine PNG." + }, + "pdfToWebp": { + "name": "PDF in WebP", + "subtitle": "Converti ogni pagina del PDF in un'immagine WebP." + }, + "pdfToBmp": { + "name": "PDF in BMP", + "subtitle": "Converti ogni pagina del PDF in un'immagine BMP." + }, + "pdfToTiff": { + "name": "PDF in TIFF", + "subtitle": "Converti ogni pagina del PDF in un'immagine TIFF." + }, + "pdfToGreyscale": { + "name": "PDF in Scala di Grigi", + "subtitle": "Converti tutti i colori in scala di grigi." + }, + "pdfToJson": { + "name": "PDF in JSON", + "subtitle": "Converti file PDF in formato JSON." + }, + "ocrPdf": { + "name": "OCR PDF", + "subtitle": "Rendi un PDF ricercabile e copiabile." + }, + "alternateMix": { + "name": "Alterna e Riordina Pagine", + "subtitle": "Unisci i PDF alternando le pagine di ogni file. Conserva i segnalibri." + }, + "addAttachments": { + "name": "Aggiungi Allegati", + "subtitle": "Incorpora uno o più file nel tuo PDF." + }, + "extractAttachments": { + "name": "Estrai Allegati", + "subtitle": "Estrai tutti i file incorporati dai PDF come archivio ZIP." + }, + "editAttachments": { + "name": "Modifica Allegati", + "subtitle": "Visualizza o rimuovi gli allegati nel tuo PDF." + }, + "dividePages": { + "name": "Dividi Pagine", + "subtitle": "Dividi le pagine orizzontalmente o verticalmente." + }, + "addBlankPage": { + "name": "Aggiungi Pagina Vuota", + "subtitle": "Inserisci una pagina vuota in qualsiasi punto del tuo PDF." + }, + "reversePages": { + "name": "Inverti Pagine", + "subtitle": "Inverti l'ordine di tutte le pagine del documento." + }, + "rotatePdf": { + "name": "Ruota PDF", + "subtitle": "Ruota le pagine per multipli di 90 gradi." + }, + "rotateCustom": { + "name": "Ruota di Gradi Personalizzati", + "subtitle": "Ruota le pagine di un angolo personalizzato." + }, + "nUpPdf": { + "name": "N-Up PDF", + "subtitle": "Disponi più pagine su un unico foglio." + }, + "combineToSinglePage": { + "name": "Combina in Una Pagina", + "subtitle": "Unisci tutte le pagine in un'unica pagina continua." + }, + "viewMetadata": { + "name": "Visualizza Metadati", + "subtitle": "Ispeziona le proprietà nascoste del tuo PDF." + }, + "editMetadata": { + "name": "Modifica Metadati", + "subtitle": "Modifica autore, titolo e altre proprietà." + }, + "pdfsToZip": { + "name": "PDF in ZIP", + "subtitle": "Raggruppa più file PDF in un archivio ZIP." + }, + "comparePdfs": { + "name": "Confronta PDF", + "subtitle": "Confronta due PDF fianco a fianco." + }, + "posterizePdf": { + "name": "Posterizza PDF", + "subtitle": "Dividi una pagina grande in più pagine più piccole." + }, + "fixPageSize": { + "name": "Correggi Dimensione Pagina", + "subtitle": "Uniforma tutte le pagine a una dimensione standard." + }, + "linearizePdf": { + "name": "Linearizza PDF", + "subtitle": "Ottimizza il PDF per una visualizzazione web più veloce." + }, + "pageDimensions": { + "name": "Dimensioni Pagina", + "subtitle": "Analizza dimensione, orientamento e unità delle pagine." + }, + "removeRestrictions": { + "name": "Rimuovi Restrizioni", + "subtitle": "Rimuovi la protezione tramite password e le restrizioni di sicurezza associate ai PDF firmati digitalmente." + }, + "repairPdf": { + "name": "Ripara PDF", + "subtitle": "Recupera i dati da file PDF corrotti o danneggiati." + }, + "encryptPdf": { + "name": "Cripta PDF", + "subtitle": "Proteggi il tuo PDF aggiungendo una password." + }, + "sanitizePdf": { + "name": "Sanitizza PDF", + "subtitle": "Rimuovi metadati, annotazioni, script e altro." + }, + "decryptPdf": { + "name": "Decrittografa PDF", + "subtitle": "Sblocca il PDF rimuovendo la protezione tramite password." + }, + "flattenPdf": { + "name": "Appiattisci PDF", + "subtitle": "Rendi i campi dei moduli e le annotazioni non modificabili." + }, + "removeMetadata": { + "name": "Rimuovi metadati", + "subtitle": "Rimuovi i dati nascosti dal tuo PDF." + }, + "changePermissions": { + "name": "Modifica permessi", + "subtitle": "Imposta o modifica i permessi utente su un PDF." + }, + "odtToPdf": { + "name": "ODT in PDF", + "subtitle": "Converti file OpenDocument Text in formato PDF. Supporta più file.", + "acceptedFormats": "File ODT", + "convertButton": "Converti in PDF" + }, + "csvToPdf": { + "name": "CSV in PDF", + "subtitle": "Converti file di foglio di calcolo CSV in formato PDF. Supporta più file.", + "acceptedFormats": "File CSV", + "convertButton": "Converti in PDF" + }, + "rtfToPdf": { + "name": "RTF in PDF", + "subtitle": "Converti documenti Rich Text Format in PDF. Supporta più file.", + "acceptedFormats": "File RTF", + "convertButton": "Converti in PDF" + }, + "wordToPdf": { + "name": "Word in PDF", + "subtitle": "Converti documenti Word (DOCX, DOC, ODT, RTF) in formato PDF. Supporta più file.", + "acceptedFormats": "File DOCX, DOC, ODT, RTF", + "convertButton": "Converti in PDF" + }, + "excelToPdf": { + "name": "Excel in PDF", + "subtitle": "Converti fogli Excel (XLSX, XLS, ODS, CSV) in formato PDF. Supporta più file.", + "acceptedFormats": "File XLSX, XLS, ODS, CSV", + "convertButton": "Converti in PDF" + }, + "powerpointToPdf": { + "name": "PowerPoint in PDF", + "subtitle": "Converti presentazioni PowerPoint (PPTX, PPT, ODP) in formato PDF. Supporta più file.", + "acceptedFormats": "File PPTX, PPT, ODP", + "convertButton": "Converti in PDF" + }, + "markdownToPdf": { + "name": "Markdown in PDF", + "subtitle": "Scrivi o incolla Markdown ed esportalo come un PDF ben formattato.", + "paneMarkdown": "Markdown", + "panePreview": "Anteprima", + "btnUpload": "Carica", + "btnSyncScroll": "Sincronizza scorrimento", + "btnSettings": "Impostazioni", + "btnExportPdf": "Esporta PDF", + "settingsTitle": "Impostazioni Markdown", + "settingsPreset": "Preset", + "presetDefault": "Predefinito (simile a GFM)", + "presetCommonmark": "CommonMark (rigoroso)", + "presetZero": "Minimale (nessuna funzionalità)", + "settingsOptions": "Opzioni Markdown", + "optAllowHtml": "Consenti tag HTML", + "optBreaks": "Converti nuove righe in
", + "optLinkify": "Converti automaticamente gli URL in link", + "optTypographer": "Tipografia (virgolette intelligenti, ecc.)" + }, + "pdfBooklet": { + "name": "Opuscolo PDF", + "subtitle": "Riorganizza le pagine per la stampa di opuscoli fronte-retro. Piega e pinza per creare un opuscolo.", + "howItWorks": "Come funziona:", + "step1": "Carica un file PDF.", + "step2": "Le pagine saranno riorganizzate in ordine per opuscolo.", + "step3": "Stampa fronte-retro, capovolgi sul lato corto, piega e pinza.", + "paperSize": "Formato carta", + "orientation": "Orientamento", + "portrait": "Ritratto", + "landscape": "Paesaggio", + "pagesPerSheet": "Pagine per foglio", + "createBooklet": "Crea opuscolo", + "processing": "Elaborazione...", + "pageCount": "Il conteggio delle pagine verrà arrotondato ad un multiplo di 4 se necessario." + }, + "xpsToPdf": { + "name": "XPS in PDF", + "subtitle": "Converti documenti XPS/OXPS in formato PDF. Supporta più file.", + "acceptedFormats": "File XPS, OXPS", + "convertButton": "Converti in PDF" + }, + "mobiToPdf": { + "name": "MOBI in PDF", + "subtitle": "Converti e-book MOBI in formato PDF. Supporta più file.", + "acceptedFormats": "File MOBI", + "convertButton": "Converti in PDF" + }, + "epubToPdf": { + "name": "EPUB in PDF", + "subtitle": "Converti e-book EPUB in formato PDF. Supporta più file.", + "acceptedFormats": "File EPUB", + "convertButton": "Converti in PDF" + }, + "fb2ToPdf": { + "name": "FB2 in PDF", + "subtitle": "Converti e-book FictionBook (FB2) in formato PDF. Supporta più file.", + "acceptedFormats": "File FB2", + "convertButton": "Converti in PDF" + }, + "cbzToPdf": { + "name": "CBZ in PDF", + "subtitle": "Converti archivi di fumetti (CBZ/CBR) in formato PDF. Supporta più file.", + "acceptedFormats": "File CBZ, CBR", + "convertButton": "Converti in PDF" + }, + "wpdToPdf": { + "name": "WPD in PDF", + "subtitle": "Converti documenti WordPerfect (WPD) in formato PDF. Supporta più file.", + "acceptedFormats": "File WPD", + "convertButton": "Converti in PDF" + }, + "wpsToPdf": { + "name": "WPS in PDF", + "subtitle": "Converti documenti WPS Office in formato PDF. Supporta più file.", + "acceptedFormats": "File WPS", + "convertButton": "Converti in PDF" + }, + "xmlToPdf": { + "name": "XML in PDF", + "subtitle": "Converti documenti XML in formato PDF. Supporta più file.", + "acceptedFormats": "File XML", + "convertButton": "Converti in PDF" + }, + "pagesToPdf": { + "name": "Pages in PDF", + "subtitle": "Converti documenti Apple Pages in formato PDF. Supporta più file.", + "acceptedFormats": "File Pages", + "convertButton": "Converti in PDF" + }, + "odgToPdf": { + "name": "ODG in PDF", + "subtitle": "Converti OpenDocument Graphics (ODG) in formato PDF. Supporta più file.", + "acceptedFormats": "File ODG", + "convertButton": "Converti in PDF" + }, + "odsToPdf": { + "name": "ODS in PDF", + "subtitle": "Converti fogli OpenDocument (ODS) in formato PDF. Supporta più file.", + "acceptedFormats": "File ODS", + "convertButton": "Converti in PDF" + }, + "odpToPdf": { + "name": "ODP in PDF", + "subtitle": "Converti presentazioni OpenDocument (ODP) in formato PDF. Supporta più file.", + "acceptedFormats": "File ODP", + "convertButton": "Converti in PDF" + }, + "pubToPdf": { + "name": "PUB in PDF", + "subtitle": "Converti file Microsoft Publisher (PUB) in formato PDF. Supporta più file.", + "acceptedFormats": "File PUB", + "convertButton": "Converti in PDF" + }, + "vsdToPdf": { + "name": "VSD in PDF", + "subtitle": "Converti file Microsoft Visio (VSD, VSDX) in formato PDF. Supporta più file.", + "acceptedFormats": "File VSD, VSDX", + "convertButton": "Converti in PDF" + }, + "psdToPdf": { + "name": "PSD in PDF", + "subtitle": "Converti file Adobe Photoshop (PSD) in formato PDF. Supporta più file.", + "acceptedFormats": "File PSD", + "convertButton": "Converti in PDF" + }, + "pdfToSvg": { + "name": "PDF in SVG", + "subtitle": "Converti ogni pagina di un file PDF in un'immagine vettoriale scalabile (SVG) per qualità perfetta a qualsiasi dimensione." + }, + "extractTables": { + "name": "Estrai tabelle PDF", + "subtitle": "Estrai le tabelle dai file PDF ed esportale come CSV, JSON o Markdown." + }, + "pdfToCsv": { + "name": "PDF in CSV", + "subtitle": "Estrai tabelle dai PDF e convertili in formato CSV." + }, + "pdfToExcel": { + "name": "PDF in Excel", + "subtitle": "Estrai tabelle dai PDF e convertili in Excel (XLSX)." + }, + "pdfToText": { + "name": "PDF in Testo", + "subtitle": "Estrai il testo dai file PDF e salvalo come testo semplice (.txt). Supporta più file.", + "note": "Questo strumento funziona SOLO con PDF creati digitalmente. Per documenti scansionati o basati su immagini, usa invece il nostro strumento OCR PDF.", + "convertButton": "Estrai testo" + }, + "digitalSignPdf": { + "name": "Firma digitale PDF", + "pageTitle": "Firma digitale PDF - Aggiungi firma crittografica | BentoPDF", + "subtitle": "Aggiungi una firma digitale crittografica al tuo PDF usando certificati X.509. Supporta i formati PKCS#12 (.pfx, .p12) e PEM. La tua chiave privata non lascia mai il browser.", + "certificateSection": "Certificato", + "uploadCert": "Carica certificato (.pfx, .p12)", + "certPassword": "Password del certificato", + "certPasswordPlaceholder": "Inserisci la password del certificato", + "certInfo": "Informazioni sul certificato", + "certSubject": "Soggetto", + "certIssuer": "Emittente", + "certValidity": "Valido", + "signatureDetails": "Dettagli della firma (opzionale)", + "reason": "Motivo", + "reasonPlaceholder": "es. Approvo questo documento", + "location": "Luogo", + "locationPlaceholder": "es. Roma, Italia", + "contactInfo": "Contatto", + "contactPlaceholder": "es. email@example.com", + "applySignature": "Applica firma digitale", + "successMessage": "PDF firmato con successo! La firma può essere verificata in qualsiasi lettore PDF." + }, + "validateSignaturePdf": { + "name": "Verifica firma PDF", + "pageTitle": "Verifica firma PDF - Controlla firme digitali | BentoPDF", + "subtitle": "Verifica le firme digitali nei tuoi PDF. Controlla la validità del certificato, visualizza i dati del firmatario e conferma l'integrità del documento. Tutto avviene nel tuo browser." + }, + "emailToPdf": { + "name": "Email in PDF", + "subtitle": "Converti file email (EML, MSG) in formato PDF. Supporta esportazioni Outlook e formati email standard.", + "acceptedFormats": "File EML, MSG", + "convertButton": "Converti in PDF" + }, + "fontToOutline": { + "name": "Font in Contorni", + "subtitle": "Converti tutti i font in contorni vettoriali per una visualizzazione coerente su tutti i dispositivi." + }, + "deskewPdf": { + "name": "Raddrizza PDF", + "subtitle": "Raddrizza automaticamente le pagine scansionate inclinate usando OpenCV." + } +} diff --git a/public/locales/pt/common.json b/public/locales/pt/common.json new file mode 100644 index 0000000..e446088 --- /dev/null +++ b/public/locales/pt/common.json @@ -0,0 +1,323 @@ +{ + "nav": { + "home": "Início", + "about": "Sobre", + "contact": "Contato", + "licensing": "Licenciamento", + "allTools": "Todas as Ferramentas", + "openMainMenu": "Abrir menu principal", + "language": "Idioma" + }, + "donation": { + "message": "Adora o BentoPDF? Ajude-nos a mantê-lo gratuito e de código aberto!", + "button": "Doar" + }, + "hero": { + "title": "O", + "pdfToolkit": "Kit de Ferramentas PDF", + "builtForPrivacy": "feito para sua privacidade", + "noSignups": "Sem Cadastros", + "unlimitedUse": "Uso Ilimitado", + "worksOffline": "Funciona Offline", + "startUsing": "Comece a Usar Agora" + }, + "usedBy": { + "title": "Usado por empresas e pessoas que trabalham em" + }, + "features": { + "title": "Por que escolher o", + "bentoPdf": "BentoPDF?", + "noSignup": { + "title": "Sem Cadastro", + "description": "Comece instantaneamente, sem contas ou e-mails." + }, + "noUploads": { + "title": "Sem Uploads", + "description": "100% no navegador, seus arquivos nunca saem do seu dispositivo." + }, + "foreverFree": { + "title": "Sempre Grátis", + "description": "Todas as ferramentas, sem testes ou assinaturas." + }, + "noLimits": { + "title": "Sem Limites", + "description": "Use o quanto quiser, sem taxas escondidas." + }, + "batchProcessing": { + "title": "Processamento em Lote", + "description": "Gerencie vários PDFs de uma só vez." + }, + "lightningFast": { + "title": "Super Rápido", + "description": "Processe PDFs instantaneamente, sem esperas ou atrasos." + } + }, + "tools": { + "title": "Comece com as", + "toolsLabel": "Ferramentas", + "subtitle": "Clique em uma ferramenta para abrir o seletor de arquivos", + "searchPlaceholder": "Buscar ferramenta (ex: 'dividir', 'organizar'...)", + "backToTools": "Voltar para Ferramentas", + "firstLoadNotice": "O primeiro carregamento demora um momento enquanto baixamos nosso mecanismo de conversão. Depois disso, todos os carregamentos serão instantâneos." + }, + "upload": { + "clickToSelect": "Clique para selecionar um arquivo", + "orDragAndDrop": "ou arraste e solte", + "pdfOrImages": "PDFs ou Imagens", + "filesNeverLeave": "Seus arquivos nunca saem do seu dispositivo.", + "addMore": "Adicionar Mais Arquivos", + "clearAll": "Limpar Tudo" + }, + "loader": { + "processing": "Processando..." + }, + "alert": { + "title": "Alerta", + "ok": "OK" + }, + "preview": { + "title": "Visualização do Documento", + "downloadAsPdf": "Baixar como PDF", + "close": "Fechar" + }, + "settings": { + "title": "Configurações", + "shortcuts": "Atalhos", + "preferences": "Preferências", + "displayPreferences": "Preferências de Exibição", + "searchShortcuts": "Buscar atalhos...", + "shortcutsInfo": "Mantenha as teclas pressionadas para definir um atalho. As alterações são salvas automaticamente.", + "shortcutsWarning": "⚠️ Evite atalhos comuns do navegador (Cmd/Ctrl+W, T, N etc.), pois podem não funcionar corretamente.", + "import": "Importar", + "export": "Exportar", + "resetToDefaults": "Restaurar Padrões", + "fullWidthMode": "Modo Largura Total", + "fullWidthDescription": "Usa toda a largura da tela para as ferramentas em vez de um container centralizado", + "settingsAutoSaved": "As configurações são salvas automaticamente", + "clickToSet": "Clique para definir", + "pressKeys": "Pressione as teclas...", + "warnings": { + "alreadyInUse": "Atalho Já em Uso", + "assignedTo": "já está atribuído a:", + "chooseDifferent": "Por favor, escolha um atalho diferente.", + "reserved": "Aviso de Atalho Reservado", + "commonlyUsed": "é comumente usado para:", + "unreliable": "Este atalho pode não funcionar bem ou conflitar com o navegador/sistema.", + "useAnyway": "Deseja usar mesmo assim?", + "resetTitle": "Redefinir Atalhos", + "resetMessage": "Tem certeza que deseja redefinir todos os atalhos?

Esta ação não pode ser desfeita.", + "importSuccessTitle": "Importação Concluída", + "importSuccessMessage": "Atalhos importados com sucesso!", + "importFailTitle": "Falha na Importação", + "importFailMessage": "Falha ao importar atalhos. Formato de arquivo inválido." + } + }, + "warning": { + "title": "Aviso", + "cancel": "Cancelar", + "proceed": "Prosseguir" + }, + "compliance": { + "title": "Seus dados nunca saem do seu dispositivo", + "weKeep": "Mantemos", + "yourInfoSafe": "suas informações seguras", + "byFollowingStandards": "seguindo padrões globais de segurança.", + "processingLocal": "Todo o processamento acontece localmente no seu dispositivo.", + "gdpr": { + "title": "Conformidade GDPR", + "description": "Protege os dados pessoais e a privacidade de indivíduos na União Europeia." + }, + "ccpa": { + "title": "Conformidade CCPA", + "description": "Dá aos residentes da Califórnia direitos sobre como suas informações pessoais são coletadas e usadas." + }, + "hipaa": { + "title": "Conformidade HIPAA", + "description": "Estabelece salvaguardas para o tratamento de informações de saúde sensíveis nos Estados Unidos." + } + }, + "faq": { + "title": "Perguntas", + "questions": "Frequentes", + "isFree": { + "question": "O BentoPDF é realmente grátis?", + "answer": "Sim, com certeza. Todas as ferramentas do BentoPDF são 100% gratuitas, sem limites de arquivos, sem cadastros e sem marcas d'água. Acreditamos que todos merecem acesso a ferramentas PDF poderosas sem barreiras financeiras." + }, + "areFilesSecure": { + "question": "Meus arquivos estão seguros? Onde são processados?", + "answer": "Seus arquivos estão o mais seguros possível porque nunca saem do seu computador. Todo o processamento ocorre diretamente no seu navegador (client-side). Nunca fazemos upload para um servidor, garantindo privacidade total." + }, + "platforms": { + "question": "Funciona no Mac, Windows e Celular?", + "answer": "Sim! Como o BentoPDF roda inteiramente no navegador, funciona em qualquer sistema operacional moderno, incluindo Windows, macOS, Linux, iOS e Android." + }, + "gdprCompliant": { + "question": "O BentoPDF está em conformidade com a GDPR?", + "answer": "Sim. Como o processamento é local e não coletamos seus arquivos, não temos acesso aos seus dados. Isso garante total conformidade e controle por parte do usuário." + }, + "dataStorage": { + "question": "Vocês armazenam ou rastreiam meus arquivos?", + "answer": "Não. Nunca armazenamos, rastreamos ou registramos seus arquivos. Tudo acontece na memória do navegador e desaparece ao fechar a página. Não há logs nem servidores envolvidos." + }, + "different": { + "question": "O que torna o BentoPDF diferente de outras ferramentas?", + "answer": "A maioria das ferramentas faz upload dos arquivos para um servidor. O BentoPDF usa tecnologia web moderna para processar tudo localmente no seu navegador, garantindo mais velocidade e privacidade." + }, + "browserBased": { + "question": "Como o processamento no navegador me mantém seguro?", + "answer": "Ao rodar no seu dispositivo, eliminamos riscos de ataques a servidores ou vazamentos de dados de terceiros. Seus arquivos permanecem seus — sempre." + }, + "analytics": { + "question": "Vocês usam cookies ou rastreamento?", + "answer": "Usamos apenas o Simple Analytics para contar visitas de forma anônima. Sabemos quantos usuários nos visitam, mas nunca quem você é. O sistema respeita totalmente a GDPR." + } + }, + "testimonials": { + "title": "O que nossos", + "users": "Usuários", + "say": "Dizem" + }, + "support": { + "title": "Gostou do Trabalho?", + "description": "O BentoPDF é um projeto pessoal feito para fornecer ferramentas poderosas e privadas para todos. Se for útil para você, considere apoiar o desenvolvimento!", + "buyMeCoffee": "Pague um Café" + }, + "footer": { + "copyright": "© 2026 BentoPDF. Todos os direitos reservados.", + "version": "Versão", + "company": "Empresa", + "aboutUs": "Sobre Nós", + "faqLink": "FAQ", + "contactUs": "Contato", + "legal": "Jurídico", + "termsAndConditions": "Termos e Condições", + "privacyPolicy": "Política de Privacidade", + "followUs": "Siga-nos" + }, + "merge": { + "title": "Mesclar PDFs", + "description": "Combine arquivos inteiros ou selecione páginas específicas para criar um novo documento.", + "fileMode": "Modo Arquivo", + "pageMode": "Modo Página", + "howItWorks": "Como funciona:", + "fileModeInstructions": [ + "Clique e arraste o ícone para alterar a ordem dos arquivos.", + "No campo \"Páginas\", você pode definir intervalos (ex: \"1-3, 5\") para mesclar apenas essas páginas.", + "Deixe o campo em branco para incluir todas as páginas do arquivo." + ], + "pageModeInstructions": [ + "Todas as páginas dos PDFs enviados aparecem abaixo.", + "Arraste as miniaturas para criar a ordem exata que deseja no novo arquivo." + ], + "mergePdfs": "Mesclar PDFs" + }, + "common": { + "page": "Página", + "pages": "Páginas", + "of": "de", + "download": "Baixar", + "cancel": "Cancelar", + "save": "Salvar", + "delete": "Excluir", + "edit": "Editar", + "add": "Adicionar", + "remove": "Remover", + "loading": "Carregando...", + "error": "Erro", + "success": "Sucesso", + "file": "Arquivo", + "files": "Arquivos" + }, + "about": { + "hero": { + "title": "Acreditamos que ferramentas PDF devem ser", + "subtitle": "rápidas, privadas e gratuitas.", + "noCompromises": "Sem concessões." + }, + "mission": { + "title": "Nossa Missão", + "description": "Fornecer o kit de ferramentas PDF mais completo, respeitando sua privacidade e sem cobrar por isso. Ferramentas essenciais devem ser acessíveis a todos, sem barreiras." + }, + "philosophy": { + "label": "Nossa Filosofia", + "title": "Privacidade Primeiro. Sempre.", + "description": "Em uma era onde dados são mercadoria, seguimos outro caminho. Todo o processamento ocorre no seu navegador. Arquivos não tocam nossos servidores e não rastreamos você. Privacidade não é apenas um recurso; é nossa base." + }, + "whyBentopdf": { + "title": "Por que o BentoPDF?", + "speed": { + "title": "Feito para Velocidade", + "description": "Sem esperas de upload. Usando tecnologias como WebAssembly, processamos tudo diretamente no navegador com velocidade inigualável." + }, + "free": { + "title": "Totalmente Grátis", + "description": "Sem períodos de teste, assinaturas ou funções \"premium\" bloqueadas. Acreditamos em ferramentas como um serviço público." + }, + "noAccount": { + "title": "Sem Necessidade de Conta", + "description": "Use qualquer ferramenta imediatamente. Não pedimos e-mail, senha ou qualquer dado pessoal. Seu fluxo de trabalho deve ser anônimo." + }, + "openSource": { + "title": "Espírito Open Source", + "description": "Construído com transparência. Utilizamos bibliotecas incríveis como PDF-lib e PDF.js para democratizar o acesso a ferramentas poderosas." + } + }, + "cta": { + "title": "Pronto para começar?", + "description": "Junte-se a milhares de usuários que confiam no BentoPDF. Sinta a diferença da privacidade e do desempenho.", + "button": "Explorar Ferramentas" + } + }, + "contact": { + "title": "Entre em Contato", + "subtitle": "Adoraríamos ouvir você. Se tiver dúvidas, feedback ou sugestões de recursos, não hesite em nos contatar.", + "email": "Você pode nos contatar diretamente por e-mail em:" + }, + "licensing": { + "title": "Licenciamento de", + "subtitle": "Escolha a licença que melhor atende às suas necessidades." + }, + "multiTool": { + "uploadPdfs": "Enviar PDFs", + "upload": "Enviar", + "addBlankPage": "Adicionar Página em Branco", + "edit": "Editar:", + "undo": "Desfazer", + "redo": "Refazer", + "reset": "Redefinir", + "selection": "Seleção:", + "selectAll": "Selecionar Tudo", + "deselectAll": "Desmarcar Tudo", + "rotate": "Girar:", + "rotateLeft": "Esquerda", + "rotateRight": "Direita", + "transform": "Transformar:", + "duplicate": "Duplicar", + "split": "Dividir", + "clear": "Limpar:", + "delete": "Excluir", + "download": "Baixar:", + "downloadSelected": "Baixar Selecionadas", + "exportPdf": "Exportar PDF", + "uploadPdfFiles": "Selecionar Arquivos PDF", + "dragAndDrop": "Arraste arquivos PDF aqui ou clique para selecionar", + "selectFiles": "Selecionar Arquivos", + "renderingPages": "Renderizando páginas...", + "actions": { + "duplicatePage": "Duplicar esta página", + "deletePage": "Excluir esta página", + "insertPdf": "Inserir PDF após esta página", + "toggleSplit": "Alternar divisão após esta página" + }, + "pleaseWait": "Aguarde", + "pagesRendering": "As páginas ainda estão sendo renderizadas. Por favor, aguarde...", + "noPagesSelected": "Nenhuma Página Selecionada", + "selectOnePage": "Selecione pelo menos uma página para baixar.", + "noPages": "Sem Páginas", + "noPagesToExport": "Não há páginas para exportar.", + "renderingTitle": "Renderizando visualizações das páginas", + "errorRendering": "Falha ao renderizar miniaturas das páginas", + "error": "Erro", + "failedToLoad": "Falha ao carregar" + } +} diff --git a/public/locales/pt/tools.json b/public/locales/pt/tools.json new file mode 100644 index 0000000..eb42770 --- /dev/null +++ b/public/locales/pt/tools.json @@ -0,0 +1,511 @@ +{ + "categories": { + "popularTools": "Ferramentas Populares", + "editAnnotate": "Editar e Anotar", + "convertToPdf": "Converter para PDF", + "convertFromPdf": "Converter de PDF", + "organizeManage": "Organizar e Gerenciar", + "optimizeRepair": "Otimizar e Reparar", + "securePdf": "Segurança de PDF" + }, + "pdfMultiTool": { + "name": "Multiferramenta PDF", + "subtitle": "Mesclar, dividir, organizar, excluir, girar, adicionar páginas em branco, extrair e duplicar em uma única interface." + }, + "mergePdf": { + "name": "Mesclar PDF", + "subtitle": "Combine vários PDFs em um único arquivo. Preserva os favoritos (bookmarks)." + }, + "splitPdf": { + "name": "Dividir PDF", + "subtitle": "Extraia um intervalo de páginas para um novo PDF." + }, + "compressPdf": { + "name": "Comprimir PDF", + "subtitle": "Reduza o tamanho do arquivo do seu PDF." + }, + "pdfEditor": { + "name": "Editor de PDF", + "subtitle": "Anotar, destacar, redigir, comentar, adicionar formas/imagens, pesquisar e visualizar PDFs." + }, + "jpgToPdf": { + "name": "JPG para PDF", + "subtitle": "Crie um PDF a partir de uma ou mais imagens JPG." + }, + "signPdf": { + "name": "Assinar PDF", + "subtitle": "Desenhe, digite ou faça upload da sua assinatura." + }, + "cropPdf": { + "name": "Cortar PDF", + "subtitle": "Corte as margens de cada página do seu PDF." + }, + "extractPages": { + "name": "Extrair Páginas", + "subtitle": "Salve uma seleção de páginas como novos arquivos." + }, + "duplicateOrganize": { + "name": "Duplicar e Organizar", + "subtitle": "Duplique, reordene e exclua páginas." + }, + "deletePages": { + "name": "Excluir Páginas", + "subtitle": "Remova páginas específicas do seu documento." + }, + "editBookmarks": { + "name": "Editar Favoritos", + "subtitle": "Adicione, edite, importe, exclua e extraia favoritos de PDF." + }, + "tableOfContents": { + "name": "Sumário", + "subtitle": "Gere uma página de sumário a partir dos favoritos do PDF." + }, + "pageNumbers": { + "name": "Números de Página", + "subtitle": "Insira números de página no seu documento." + }, + "addWatermark": { + "name": "Adicionar Marca d'Água", + "subtitle": "Carimbe texto ou uma imagem sobre as páginas do seu PDF." + }, + "headerFooter": { + "name": "Cabeçalho e Rodapé", + "subtitle": "Adicione texto no topo e no final das páginas." + }, + "invertColors": { + "name": "Inverter Cores", + "subtitle": "Crie uma versão em \"modo escuro\" do seu PDF." + }, + "backgroundColor": { + "name": "Cor de Fundo", + "subtitle": "Altere a cor de fundo do seu PDF." + }, + "changeTextColor": { + "name": "Alterar Cor do Texto", + "subtitle": "Altere a cor do texto no seu PDF." + }, + "addStamps": { + "name": "Adicionar Carimbos", + "subtitle": "Adicione carimbos de imagem ao seu PDF usando a barra de ferramentas de anotação.", + "usernameLabel": "Nome do Usuário no Carimbo", + "usernamePlaceholder": "Digite seu nome (para os carimbos)", + "usernameHint": "Este nome aparecerá nos carimbos que você criar." + }, + "removeAnnotations": { + "name": "Remover Anotações", + "subtitle": "Remova comentários, destaques e links." + }, + "pdfFormFiller": { + "name": "Preenchimento de Formulário", + "subtitle": "Preencha formulários diretamente no navegador. Também suporta formulários XFA." + }, + "createPdfForm": { + "name": "Criar Formulário PDF", + "subtitle": "Crie formulários PDF preenchíveis com campos de texto de arrastar e soltar." + }, + "removeBlankPages": { + "name": "Remover Páginas em Branco", + "subtitle": "Detecte e exclua automaticamente páginas em branco." + }, + "imageToPdf": { + "name": "Imagem para PDF", + "subtitle": "Converta JPG, PNG, WebP, BMP, TIFF, SVG, HEIC para PDF." + }, + "pngToPdf": { + "name": "PNG para PDF", + "subtitle": "Crie um PDF a partir de uma ou mais imagens PNG." + }, + "webpToPdf": { + "name": "WebP para PDF", + "subtitle": "Crie um PDF a partir de uma ou mais imagens WebP." + }, + "svgToPdf": { + "name": "SVG para PDF", + "subtitle": "Crie um PDF a partir de uma ou mais imagens SVG." + }, + "bmpToPdf": { + "name": "BMP para PDF", + "subtitle": "Crie um PDF a partir de uma ou mais imagens BMP." + }, + "heicToPdf": { + "name": "HEIC para PDF", + "subtitle": "Crie um PDF a partir de uma ou mais imagens HEIC." + }, + "tiffToPdf": { + "name": "TIFF para PDF", + "subtitle": "Crie um PDF a partir de uma ou mais imagens TIFF." + }, + "textToPdf": { + "name": "Texto para PDF", + "subtitle": "Converta um arquivo de texto simples (.txt) em PDF." + }, + "jsonToPdf": { + "name": "JSON para PDF", + "subtitle": "Converta arquivos JSON para o formato PDF." + }, + "pdfToJpg": { + "name": "PDF para JPG", + "subtitle": "Converta cada página do PDF em uma imagem JPG." + }, + "pdfToPng": { + "name": "PDF para PNG", + "subtitle": "Converta cada página do PDF em uma imagem PNG." + }, + "pdfToWebp": { + "name": "PDF para WebP", + "subtitle": "Converta cada página do PDF em uma imagem WebP." + }, + "pdfToBmp": { + "name": "PDF para BMP", + "subtitle": "Converta cada página do PDF em uma imagem BMP." + }, + "pdfToTiff": { + "name": "PDF para TIFF", + "subtitle": "Converta cada página do PDF em uma imagem TIFF." + }, + "pdfToGreyscale": { + "name": "PDF para Tons de Cinza", + "subtitle": "Converta todas as cores para preto e branco." + }, + "pdfToJson": { + "name": "PDF para JSON", + "subtitle": "Converta arquivos PDF para o formato JSON." + }, + "ocrPdf": { + "name": "OCR PDF", + "subtitle": "Torne um PDF pesquisável e copiável (reconhecimento de texto)." + }, + "alternateMix": { + "name": "Alternar e Misturar Páginas", + "subtitle": "Mescle PDFs alternando as páginas de cada arquivo. Preserva os favoritos." + }, + "addAttachments": { + "name": "Adicionar Anexos", + "subtitle": "Incorpore um ou mais arquivos dentro do seu PDF." + }, + "extractAttachments": { + "name": "Extrair Anexos", + "subtitle": "Extraia todos os arquivos incorporados de PDF(s) como um ZIP." + }, + "editAttachments": { + "name": "Editar Anexos", + "subtitle": "Visualize ou remova anexos do seu PDF." + }, + "dividePages": { + "name": "Dividir Páginas", + "subtitle": "Divida as páginas horizontalmente ou verticalmente." + }, + "addBlankPage": { + "name": "Adicionar Página em Branco", + "subtitle": "Insira uma página vazia em qualquer lugar do seu PDF." + }, + "reversePages": { + "name": "Inverter Páginas", + "subtitle": "Inverta a ordem de todas as páginas do seu documento." + }, + "rotatePdf": { + "name": "Girar PDF", + "subtitle": "Gire as páginas em incrementos de 90 graus." + }, + "nUpPdf": { + "name": "PDF N-Up", + "subtitle": "Organize várias páginas em uma única folha de impressão." + }, + "combineToSinglePage": { + "name": "Combinar em Página Única", + "subtitle": "Costure todas as páginas em um único fluxo contínuo." + }, + "viewMetadata": { + "name": "Ver Metadados", + "subtitle": "Inspecione as propriedades ocultas do seu PDF." + }, + "editMetadata": { + "name": "Editar Metadados", + "subtitle": "Altere o autor, título e outras propriedades." + }, + "pdfsToZip": { + "name": "PDFs para ZIP", + "subtitle": "Empacote vários arquivos PDF em um arquivo compactado ZIP." + }, + "comparePdfs": { + "name": "Comparar PDFs", + "subtitle": "Compare dois PDFs lado a lado." + }, + "posterizePdf": { + "name": "Posterizar PDF", + "subtitle": "Divida uma página grande em várias páginas menores." + }, + "fixPageSize": { + "name": "Ajustar Tamanho da Página", + "subtitle": "Padronize todas as páginas para um tamanho uniforme." + }, + "linearizePdf": { + "name": "Linearizar PDF", + "subtitle": "Otimize o PDF para visualização rápida na web." + }, + "pageDimensions": { + "name": "Dimensões da Página", + "subtitle": "Analise o tamanho, orientação e unidades das páginas." + }, + "removeRestrictions": { + "name": "Remover Restrições", + "subtitle": "Remova proteção por senha e restrições de segurança de arquivos assinados digitalmente." + }, + "repairPdf": { + "name": "Reparar PDF", + "subtitle": "Recupere dados de arquivos PDF corrompidos ou danificados." + }, + "encryptPdf": { + "name": "Criptografar PDF", + "subtitle": "Bloqueie seu PDF adicionando uma senha." + }, + "sanitizePdf": { + "name": "Sanitizar PDF", + "subtitle": "Remova metadados, anotações, scripts e outros dados ocultos." + }, + "decryptPdf": { + "name": "Descriptografar PDF", + "subtitle": "Desbloqueie o PDF removendo a proteção por senha." + }, + "flattenPdf": { + "name": "Achatar PDF (Flatten)", + "subtitle": "Torne os campos de formulário e anotações não editáveis." + }, + "removeMetadata": { + "name": "Remover Metadados", + "subtitle": "Limpe dados ocultos do seu PDF." + }, + "changePermissions": { + "name": "Alterar Permissões", + "subtitle": "Defina ou altere as permissões de usuário em um PDF." + }, + "emailToPdf": { + "name": "Email para PDF", + "subtitle": "Converta arquivos de email (EML, MSG) para PDF. Suporta exportações do Outlook e formatos de email padrão.", + "acceptedFormats": "Arquivos EML, MSG", + "convertButton": "Converter para PDF" + }, + "fontToOutline": { + "name": "Fonte para Contorno", + "subtitle": "Converta todas as fontes em contornos vetoriais para renderização consistente em todos os dispositivos." + }, + "deskewPdf": { + "name": "Desinclinar PDF", + "subtitle": "Endireite automaticamente páginas digitalizadas inclinadas usando OpenCV." + }, + "rotateCustom": { + "name": "Rotate by Custom Degrees", + "subtitle": "Rotate pages by any custom angle." + }, + "odtToPdf": { + "name": "ODT to PDF", + "subtitle": "Convert OpenDocument Text files to PDF format. Supports multiple files.", + "acceptedFormats": "ODT files", + "convertButton": "Convert to PDF" + }, + "csvToPdf": { + "name": "CSV to PDF", + "subtitle": "Convert CSV spreadsheet files to PDF format. Supports multiple files.", + "acceptedFormats": "CSV files", + "convertButton": "Convert to PDF" + }, + "rtfToPdf": { + "name": "RTF to PDF", + "subtitle": "Convert Rich Text Format documents to PDF. Supports multiple files.", + "acceptedFormats": "RTF files", + "convertButton": "Convert to PDF" + }, + "wordToPdf": { + "name": "Word to PDF", + "subtitle": "Convert Word documents (DOCX, DOC, ODT, RTF) to PDF format. Supports multiple files.", + "acceptedFormats": "DOCX, DOC, ODT, RTF files", + "convertButton": "Convert to PDF" + }, + "excelToPdf": { + "name": "Excel to PDF", + "subtitle": "Convert Excel spreadsheets (XLSX, XLS, ODS, CSV) to PDF format. Supports multiple files.", + "acceptedFormats": "XLSX, XLS, ODS, CSV files", + "convertButton": "Convert to PDF" + }, + "powerpointToPdf": { + "name": "PowerPoint to PDF", + "subtitle": "Convert PowerPoint presentations (PPTX, PPT, ODP) to PDF format. Supports multiple files.", + "acceptedFormats": "PPTX, PPT, ODP files", + "convertButton": "Convert to PDF" + }, + "markdownToPdf": { + "name": "Markdown to PDF", + "subtitle": "Write or paste Markdown and export it as a beautifully formatted PDF.", + "paneMarkdown": "Markdown", + "panePreview": "Preview", + "btnUpload": "Upload", + "btnSyncScroll": "Sync Scroll", + "btnSettings": "Settings", + "btnExportPdf": "Export PDF", + "settingsTitle": "Markdown Settings", + "settingsPreset": "Preset", + "presetDefault": "Default (GFM-like)", + "presetCommonmark": "CommonMark (strict)", + "presetZero": "Minimal (no features)", + "settingsOptions": "Markdown Options", + "optAllowHtml": "Allow HTML tags", + "optBreaks": "Convert newlines to
", + "optLinkify": "Auto-convert URLs to links", + "optTypographer": "Typographer (smart quotes, etc.)" + }, + "pdfBooklet": { + "name": "PDF Booklet", + "subtitle": "Rearrange pages for double-sided booklet printing. Fold and staple to create a booklet.", + "howItWorks": "How it works:", + "step1": "Upload a PDF file.", + "step2": "Pages will be rearranged in booklet order.", + "step3": "Print double-sided, flip on short edge, fold and staple.", + "paperSize": "Paper Size", + "orientation": "Orientation", + "portrait": "Portrait", + "landscape": "Landscape", + "pagesPerSheet": "Pages per Sheet", + "createBooklet": "Create Booklet", + "processing": "Processing...", + "pageCount": "Page count will be padded to multiple of 4 if needed." + }, + "xpsToPdf": { + "name": "XPS to PDF", + "subtitle": "Convert XPS/OXPS documents to PDF format. Supports multiple files.", + "acceptedFormats": "XPS, OXPS files", + "convertButton": "Convert to PDF" + }, + "mobiToPdf": { + "name": "MOBI to PDF", + "subtitle": "Convert MOBI e-books to PDF format. Supports multiple files.", + "acceptedFormats": "MOBI files", + "convertButton": "Convert to PDF" + }, + "epubToPdf": { + "name": "EPUB to PDF", + "subtitle": "Convert EPUB e-books to PDF format. Supports multiple files.", + "acceptedFormats": "EPUB files", + "convertButton": "Convert to PDF" + }, + "fb2ToPdf": { + "name": "FB2 to PDF", + "subtitle": "Convert FictionBook (FB2) e-books to PDF format. Supports multiple files.", + "acceptedFormats": "FB2 files", + "convertButton": "Convert to PDF" + }, + "cbzToPdf": { + "name": "CBZ to PDF", + "subtitle": "Convert comic book archives (CBZ/CBR) to PDF format. Supports multiple files.", + "acceptedFormats": "CBZ, CBR files", + "convertButton": "Convert to PDF" + }, + "wpdToPdf": { + "name": "WPD to PDF", + "subtitle": "Convert WordPerfect documents (WPD) to PDF format. Supports multiple files.", + "acceptedFormats": "WPD files", + "convertButton": "Convert to PDF" + }, + "wpsToPdf": { + "name": "WPS to PDF", + "subtitle": "Convert WPS Office documents to PDF format. Supports multiple files.", + "acceptedFormats": "WPS files", + "convertButton": "Convert to PDF" + }, + "xmlToPdf": { + "name": "XML to PDF", + "subtitle": "Convert XML documents to PDF format. Supports multiple files.", + "acceptedFormats": "XML files", + "convertButton": "Convert to PDF" + }, + "pagesToPdf": { + "name": "Pages to PDF", + "subtitle": "Convert Apple Pages documents to PDF format. Supports multiple files.", + "acceptedFormats": "Pages files", + "convertButton": "Convert to PDF" + }, + "odgToPdf": { + "name": "ODG to PDF", + "subtitle": "Convert OpenDocument Graphics (ODG) files to PDF format. Supports multiple files.", + "acceptedFormats": "ODG files", + "convertButton": "Convert to PDF" + }, + "odsToPdf": { + "name": "ODS to PDF", + "subtitle": "Convert OpenDocument Spreadsheet (ODS) files to PDF format. Supports multiple files.", + "acceptedFormats": "ODS files", + "convertButton": "Convert to PDF" + }, + "odpToPdf": { + "name": "ODP to PDF", + "subtitle": "Convert OpenDocument Presentation (ODP) files to PDF format. Supports multiple files.", + "acceptedFormats": "ODP files", + "convertButton": "Convert to PDF" + }, + "pubToPdf": { + "name": "PUB to PDF", + "subtitle": "Convert Microsoft Publisher (PUB) files to PDF format. Supports multiple files.", + "acceptedFormats": "PUB files", + "convertButton": "Convert to PDF" + }, + "vsdToPdf": { + "name": "VSD to PDF", + "subtitle": "Convert Microsoft Visio (VSD, VSDX) files to PDF format. Supports multiple files.", + "acceptedFormats": "VSD, VSDX files", + "convertButton": "Convert to PDF" + }, + "psdToPdf": { + "name": "PSD to PDF", + "subtitle": "Convert Adobe Photoshop (PSD) files to PDF format. Supports multiple files.", + "acceptedFormats": "PSD files", + "convertButton": "Convert to PDF" + }, + "pdfToSvg": { + "name": "PDF to SVG", + "subtitle": "Convert each page of a PDF file into a scalable vector graphic (SVG) for perfect quality at any size." + }, + "extractTables": { + "name": "Extract PDF Tables", + "subtitle": "Extract tables from PDF files and export as CSV, JSON, or Markdown." + }, + "pdfToCsv": { + "name": "PDF to CSV", + "subtitle": "Extract tables from PDF and convert to CSV format." + }, + "pdfToExcel": { + "name": "PDF to Excel", + "subtitle": "Extract tables from PDF and convert to Excel (XLSX) format." + }, + "pdfToText": { + "name": "PDF to Text", + "subtitle": "Extract text from PDF files and save as plain text (.txt). Supports multiple files.", + "note": "This tool works ONLY with digitally created PDFs. For scanned documents or image-based PDFs, use our OCR PDF tool instead.", + "convertButton": "Extract Text" + }, + "digitalSignPdf": { + "name": "Assinatura Digital PDF", + "pageTitle": "Assinatura Digital PDF - Adicionar Assinatura Criptográfica | BentoPDF", + "subtitle": "Adicione uma assinatura digital criptográfica ao seu PDF usando certificados X.509. Suporta formatos PKCS#12 (.pfx, .p12) e PEM. Sua chave privada nunca sai do seu navegador.", + "certificateSection": "Certificado", + "uploadCert": "Carregar certificado (.pfx, .p12)", + "certPassword": "Senha do Certificado", + "certPasswordPlaceholder": "Digite a senha", + "certInfo": "Informações do Certificado", + "certSubject": "Assunto", + "certIssuer": "Emissor", + "certValidity": "Válido", + "signatureDetails": "Detalhes da Assinatura (Opcional)", + "reason": "Razão", + "reasonPlaceholder": "ex: Eu aprovo este documento", + "location": "Localização", + "locationPlaceholder": "ex: Lisboa, Portugal", + "contactInfo": "Contato", + "contactPlaceholder": "ex: email@exemplo.com", + "applySignature": "Aplicar Assinatura", + "successMessage": "PDF assinado com sucesso! A assinatura pode ser verificada em qualquer leitor de PDF." + }, + "validateSignaturePdf": { + "name": "Validar Assinatura PDF", + "pageTitle": "Validar Assinatura PDF - Verificar Assinaturas Digitais | BentoPDF", + "subtitle": "Verifique assinaturas digitais em seus arquivos PDF. Verifique a validade do certificado e a integridade do documento." + } +} diff --git a/public/locales/tr/common.json b/public/locales/tr/common.json new file mode 100644 index 0000000..1c874d4 --- /dev/null +++ b/public/locales/tr/common.json @@ -0,0 +1,323 @@ +{ + "nav": { + "home": "Ana Sayfa", + "about": "Hakkımızda", + "contact": "İletişim", + "licensing": "Lisanslama", + "allTools": "Tüm Araçlar", + "openMainMenu": "Ana menüyü aç", + "language": "Dil" + }, + "donation": { + "message": "BentoPDF'i seviyor musunuz? Ücretsiz ve açık kaynaklı kalmasına yardımcı olun!", + "button": "Bağış Yap" + }, + "hero": { + "title": " ", + "pdfToolkit": "PDF Toolkit", + "builtForPrivacy": "gizlilik için tasarlandı", + "noSignups": "Kayıt Gerekmez", + "unlimitedUse": "Sınırsız Kullanım", + "worksOffline": "Çevrimdışı Çalışır", + "startUsing": "Hemen Kullanmaya Başla" + }, + "usedBy": { + "title": "Şu şirketler ve çalışanları tarafından kullanılıyor" + }, + "features": { + "title": "Neden", + "bentoPdf": "BentoPDF'yi seçmelisiniz?", + "noSignup": { + "title": "Kayıt Gerekmez", + "description": "Hemen başlayın, hesap veya e-posta gerekmez." + }, + "noUploads": { + "title": "Yükleme Yok", + "description": "%100 istemci tarafında çalışır, dosyalarınız cihazınızı asla terk etmez." + }, + "foreverFree": { + "title": "Tamamen Ücretsiz", + "description": "Tüm araçlar, deneme sürümü yok, ödeme duvarı yok." + }, + "noLimits": { + "title": "Sınırsız", + "description": "İstediğiniz kadar kullanın, gizli sınırlar yok." + }, + "batchProcessing": { + "title": "Toplu İşlem", + "description": "Sınırsız sayıda PDF'yi tek seferde işleyin." + }, + "lightningFast": { + "title": "Şimşek Hızında", + "description": "PDF'leri anında işleyin, bekleme veya gecikme olmadan." + } + }, + "tools": { + "title": "Araçlarla", + "toolsLabel": "Başlayın", + "subtitle": "Dosya yükleyiciyi açmak için bir araç seçin", + "searchPlaceholder": "Bir araç arayın (örn. 'böl', 'düzenle'...)", + "backToTools": "Araçlara Dön", + "firstLoadNotice": "Dönüştürme motorumuzu indirirken ilk yükleme biraz zaman alır. Sonrasında tüm yüklemeler anında gerçekleşir." + }, + "upload": { + "clickToSelect": "Dosya seçmek için tıklayın", + "orDragAndDrop": "veya sürükleyip bırakın", + "pdfOrImages": "PDF veya Görseller", + "filesNeverLeave": "Dosyalarınız cihazınızı asla terk etmez.", + "addMore": "Daha Fazla Dosya Ekle", + "clearAll": "Tümünü Temizle" + }, + "loader": { + "processing": "İşleniyor..." + }, + "alert": { + "title": "Uyarı", + "ok": "Tamam" + }, + "preview": { + "title": "Belge Önizleme", + "downloadAsPdf": "PDF Olarak İndir", + "close": "Kapat" + }, + "settings": { + "title": "Ayarlar", + "shortcuts": "Kısayollar", + "preferences": "Tercihler", + "displayPreferences": "Görüntü Tercihleri", + "searchShortcuts": "Kısayollarda ara...", + "shortcutsInfo": "Bir kısayol atamak için tuşlara basılı tutun. Değişiklikler otomatik olarak kaydedilir.", + "shortcutsWarning": "⚠️ Güvenilir çalışmayabileceğinden yaygın tarayıcı kısayollarından (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N vb.) kaçının.", + "import": "İçe Aktar", + "export": "Dışa Aktar", + "resetToDefaults": "Varsayılanlara Sıfırla", + "fullWidthMode": "Tam Genişlik Modu", + "fullWidthDescription": "Ortalanmış bir konteyner yerine tüm ekran genişliğini kullan", + "settingsAutoSaved": "Ayarlar otomatik olarak kaydedildi", + "clickToSet": "Ayarlamak için tıklayın", + "pressKeys": "Tuşlara basın...", + "warnings": { + "alreadyInUse": "Kısayol Zaten Kullanımda", + "assignedTo": "zaten şurada kullanılıyor:", + "chooseDifferent": "Lütfen farklı bir kısayol seçin.", + "reserved": "Ayrılmış Kısayol Uyarısı", + "commonlyUsed": "genellikle şunun için kullanılır:", + "unreliable": "Bu kısayol güvenilir çalışmayabilir veya tarayıcı/sistem davranışıyla çakışabilir.", + "useAnyway": "Yine de kullanmak istiyor musunuz?", + "resetTitle": "Kısayolları Sıfırla", + "resetMessage": "Tüm kısayolları varsayılan ayarlara sıfırlamak istediğinizden emin misiniz?

Bu işlem geri alınamaz.", + "importSuccessTitle": "İçe Aktarma Başarılı", + "importSuccessMessage": "Kısayollar başarıyla içe aktarıldı!", + "importFailTitle": "İçe Aktarma Başarısız", + "importFailMessage": "Kısayollar içe aktarılamadı. Geçersiz dosya biçimi." + } + }, + "warning": { + "title": "Uyarı", + "cancel": "İptal", + "proceed": "Devam Et" + }, + "compliance": { + "title": "Verileriniz cihazınızı asla terk etmez", + "weKeep": "Bilgilerinizi", + "yourInfoSafe": "güvende tutuyoruz", + "byFollowingStandards": "küresel güvenlik standartlarını takip ederek.", + "processingLocal": "Tüm işlemler cihazınızda yerel olarak gerçekleşir.", + "gdpr": { + "title": "GDPR uyumluluğu", + "description": "Avrupa Birliği'ndeki bireylerin kişisel verilerini ve gizliliğini korur." + }, + "ccpa": { + "title": "CCPA uyumluluğu", + "description": "Kaliforniya sakinlerine kişisel bilgilerinin nasıl toplandığı, kullanıldığı ve paylaşıldığı konusunda haklar tanır." + }, + "hipaa": { + "title": "HIPAA uyumluluğu", + "description": "ABD sağlık sisteminde hassas sağlık bilgilerinin işlenmesi için güvenlik önlemleri belirler." + } + }, + "faq": { + "title": "Sıkça Sorulan", + "questions": "Sorular", + "isFree": { + "question": "BentoPDF gerçekten ücretsiz mi?", + "answer": "Evet, kesinlikle. BentoPDF'deki tüm araçlar %100 ücretsizdir, dosya sınırı yoktur, kayıt gerekmez ve filigran eklenmez. Herkesin ödeme duvarı olmadan basit, güçlü PDF araçlarına erişimi hak ettiğine inanıyoruz." + }, + "areFilesSecure": { + "question": "Dosyalarım güvende mi? Nerede işleniyorlar?", + "answer": "Dosyalarınız mümkün olan en güvenli şekildedir çünkü bilgisayarınızı asla terk etmezler. Tüm işlemler doğrudan web tarayıcınızda (istemci tarafında) gerçekleşir. Dosyalarınızı asla bir sunucuya yüklemeyiz, böylece gizliliğiniz ve belgeleriniz üzerindeki kontrolünüz tam olarak sizde kalır." + }, + "platforms": { + "question": "Mac, Windows ve Mobil'de çalışıyor mu?", + "answer": "Evet! BentoPDF tamamen tarayıcınızda çalıştığı için, Windows, macOS, Linux, iOS ve Android dahil modern bir web tarayıcısı olan herhangi bir işletim sisteminde çalışır." + }, + "gdprCompliant": { + "question": "BentoPDF GDPR uyumlu mu?", + "answer": "Evet. BentoPDF tamamen GDPR uyumludur. Tüm dosya işlemleri tarayıcınızda yerel olarak gerçekleştiği ve dosyalarınızı herhangi bir sunucuya asla iletmediğimiz için verilerinize erişimimiz yoktur. Bu, belgeleriniz üzerindeki kontrolün her zaman sizde olduğundan emin olur." + }, + "dataStorage": { + "question": "Dosyalarımı saklıyor veya takip ediyor musunuz?", + "answer": "Hayır. Dosyalarınızı asla saklamıyor, takip etmiyor veya kaydetmiyoruz. BentoPDF'de yaptığınız her şey tarayıcı belleğinizde gerçekleşir ve sayfayı kapattığınızda silinir. Yükleme, geçmiş kaydı veya sunucu yoktur." + }, + "different": { + "question": "BentoPDF'yi diğer PDF araçlarından farklı kılan nedir?", + "answer": "Çoğu PDF aracı, işlem için dosyalarınızı bir sunucuya yükler. BentoPDF asla böyle yapmaz. Dosyalarınızı doğrudan tarayıcınızda işlemek için güvenli, modern web teknolojileri kullanırız. Bu, daha hızlı performans, daha güçlü gizlilik ve tam bir gönül rahatlığı anlamına gelir." + }, + "browserBased": { + "question": "Tarayıcı tabanlı işlem beni nasıl korur?", + "answer": "Tamamen tarayıcınızın içinde çalışarak, BentoPDF dosyalarınızın cihazınızı asla terk etmemesini sağlar. Bu, sunucu saldırıları, veri ihlalleri veya yetkisiz erişim risklerini ortadan kaldırır. Dosyalarınız her zaman sizin kalır." + }, + "analytics": { + "question": "Beni takip etmek için çerez veya analiz kullanıyor musunuz?", + "answer": "Gizliliğinizi önemsiyoruz. BentoPDF kişisel bilgileri takip etmez. Sadece anonim ziyaretçi sayılarını görmek için Simple Analytics kullanıyoruz. Bu, sitemizi kaç kişinin ziyaret ettiğini görebileceğimiz, ancak kim olduğunuzu asla bilemeyeceğimiz anlamına gelir. Simple Analytics tamamen GDPR uyumludur ve gizliliğinize saygı gösterir." + } + }, + "testimonials": { + "title": "Kullanıcılarımız", + "users": "Ne Diyor", + "say": "" + }, + "support": { + "title": "Çalışmamı Beğendiniz mi?", + "description": "BentoPDF, herkes için ücretsiz, özel ve güçlü bir PDF araç seti sağlamak amacıyla oluşturulmuş bir tutku projesidir. Faydalı bulduysanız, geliştirilmesini desteklemeyi düşünebilirsiniz. Her kahve yardımcı olur!", + "buyMeCoffee": "Bana Kahve Ismarla" + }, + "footer": { + "copyright": "© 2026 BentoPDF. Tüm hakları saklıdır.", + "version": "Sürüm", + "company": "Şirket", + "aboutUs": "Hakkımızda", + "faqLink": "SSS", + "contactUs": "İletişim", + "legal": "Yasal", + "termsAndConditions": "Kullanım Koşulları", + "privacyPolicy": "Gizlilik Politikası", + "followUs": "Bizi Takip Edin" + }, + "merge": { + "title": "PDF Birleştir", + "description": "Dosyaların tamamını birleştirin veya yeni bir belge oluşturmak için belirli sayfaları seçin.", + "fileMode": "Dosya Modu", + "pageMode": "Sayfa Modu", + "howItWorks": "Nasıl Çalışır:", + "fileModeInstructions": [ + "Dosyaların sırasını değiştirmek için simgeyi tıklayıp sürükleyin.", + "Her dosya için \"Sayfalar\" kutusuna, yalnızca o sayfaları birleştirmek için aralıklar belirtebilirsiniz (örn. \"1-3, 5\").", + "Tüm sayfaları dahil etmek için \"Sayfalar\" kutusunu boş bırakın." + ], + "pageModeInstructions": [ + "Yüklediğiniz PDF'lerin tüm sayfaları aşağıda gösterilmiştir.", + "Yeni dosyanız için istediğiniz sırayı oluşturmak üzere sayfa küçük resimlerini sürükleyip bırakmanız yeterlidir." + ], + "mergePdfs": "PDF'leri Birleştir" + }, + "common": { + "page": "Sayfa", + "pages": "Sayfa", + "of": "- ", + "download": "İndir", + "cancel": "İptal", + "save": "Kaydet", + "delete": "Sil", + "edit": "Düzenle", + "add": "Ekle", + "remove": "Kaldır", + "loading": "Yükleniyor...", + "error": "Hata", + "success": "Başarılı", + "file": "Dosya", + "files": "Dosya" + }, + "about": { + "hero": { + "title": "PDF araçlarının", + "subtitle": "hızlı, özel ve ücretsiz olması gerektiğine inanıyoruz.", + "noCompromises": "Taviz yok." + }, + "mission": { + "title": "Misyonumuz", + "description": "Gizliliğinize saygı duyan ve asla ödeme talep etmeyen en kapsamlı PDF araç setini sağlamak. Temel belge araçlarının her yerde, herkes için erişilebilir olması gerektiğine inanıyoruz." + }, + "philosophy": { + "label": "Temel Felsefemiz", + "title": "Öncelik Her Zaman Gizlilik.", + "description": "Verinin bir meta olarak kabul edildiği bir çağda, farklı bir yaklaşım benimsiyoruz. Bentopdf araçları için tüm işlemler tarayıcınızda yerel olarak gerçekleşir. Bu, dosyalarınızın sunucularımıza asla dokunmadığı, belgelerinizi asla görmediğimiz ve ne yaptığınızı takip etmediğimiz anlamına gelir. Belgeleriniz tamamen ve kesinlikle özel kalır. Bu sadece bir özellik değil, temelimizdir." + }, + "whyBentopdf": { + "title": "Neden", + "speed": { + "title": "Hız İçin Tasarlandı", + "description": "Sunucuya yükleme veya indirme için bekleme yok. WebAssembly gibi modern web teknolojilerini kullanarak dosyaları doğrudan tarayıcınızda işleyerek, tüm araçlarımız için benzersiz bir hız sunuyoruz." + }, + "free": { + "title": "Tamamen Ücretsiz", + "description": "Deneme sürümü yok, abonelik yok, gizli ücret yok ve \"premium\" özellikler rehin alınmamış. Güçlü PDF araçlarının bir kar merkezi değil, bir kamu hizmeti olması gerektiğine inanıyoruz." + }, + "noAccount": { + "title": "Hesap Gerekmez", + "description": "Hemen herhangi bir aracı kullanmaya başlayın. E-postanıza, şifrenize veya herhangi bir kişisel bilginize ihtiyacımız yok. İş akışınız sürtünmesiz ve anonim olmalıdır." + }, + "openSource": { + "title": "Açık Kaynak Ruhu", + "description": "Şeffaflık düşünülerek oluşturuldu. PDF-lib ve PDF.js gibi inanılmaz açık kaynaklı kütüphanelerden yararlanıyoruz ve güçlü araçları herkes için erişilebilir kılmak için topluluk odaklı çabaya inanıyoruz." + } + }, + "cta": { + "title": "Başlamaya hazır mısınız?", + "description": "Günlük belge ihtiyaçları için BentoPDF'ye güvenen binlerce kullanıcıya katılın. Gizlilik ve performansın yaratabileceği farkı deneyimleyin.", + "button": "Tüm Araçları Keşfet" + } + }, + "contact": { + "title": "İletişime Geçin", + "subtitle": "Sizden haber almak isteriz. Bir sorunuz, geri bildiriminiz veya bir özellik isteğiniz varsa, lütfen bize ulaşmaktan çekinmeyin.", + "email": "Bize doğrudan şu e-posta adresinden ulaşabilirsiniz:" + }, + "licensing": { + "title": "Lisanslama", + "subtitle": "İhtiyaçlarınıza uygun lisansı seçin." + }, + "multiTool": { + "uploadPdfs": "PDF Yükle", + "upload": "Yükle", + "addBlankPage": "Boş Sayfa Ekle", + "edit": "Düzenle:", + "undo": "Geri Al", + "redo": "Yinele", + "reset": "Sıfırla", + "selection": "Seçim:", + "selectAll": "Tümünü Seç", + "deselectAll": "Seçimi Kaldır", + "rotate": "Döndür:", + "rotateLeft": "Sola", + "rotateRight": "Sağa", + "transform": "Dönüştür:", + "duplicate": "Çoğalt", + "split": "Böl", + "clear": "Temizle:", + "delete": "Sil", + "download": "İndir:", + "downloadSelected": "Seçilenleri İndir", + "exportPdf": "PDF Olarak Dışa Aktar", + "uploadPdfFiles": "PDF Dosyalarını Seçin", + "dragAndDrop": "PDF dosyalarını buraya sürükleyip bırakın veya seçmek için tıklayın", + "selectFiles": "Dosya Seç", + "renderingPages": "Sayfalar oluşturuluyor...", + "actions": { + "duplicatePage": "Bu sayfayı çoğalt", + "deletePage": "Bu sayfayı sil", + "insertPdf": "Bu sayfadan sonra PDF ekle", + "toggleSplit": "Bu sayfadan sonra bölmeyi aç/kapat" + }, + "pleaseWait": "Lütfen Bekleyin", + "pagesRendering": "Sayfalar hala oluşturuluyor. Lütfen bekleyin...", + "noPagesSelected": "Hiçbir Sayfa Seçilmedi", + "selectOnePage": "Lütfen indirmek için en az bir sayfa seçin.", + "noPages": "Sayfa Yok", + "noPagesToExport": "Dışa aktarılacak sayfa yok.", + "renderingTitle": "Sayfa önizlemeleri oluşturuluyor", + "errorRendering": "Sayfa küçük resimleri oluşturulamadı", + "error": "Hata", + "failedToLoad": "Yüklenemedi" + } +} diff --git a/public/locales/tr/tools.json b/public/locales/tr/tools.json new file mode 100644 index 0000000..7f897ad --- /dev/null +++ b/public/locales/tr/tools.json @@ -0,0 +1,511 @@ +{ + "categories": { + "popularTools": "Popüler Araçlar", + "editAnnotate": "Düzenle & Açıklama Ekle", + "convertToPdf": "PDF'ye Dönüştür", + "convertFromPdf": "PDF'den Dönüştür", + "organizeManage": "Düzenle & Yönet", + "optimizeRepair": "Optimize Et & Onar", + "securePdf": "PDF Güvenliği" + }, + "pdfMultiTool": { + "name": "PDF Çoklu Araç", + "subtitle": "Birleştir, Böl, Düzenle, Sil, Döndür, Boş Sayfa Ekle, Çıkar ve Çoğalt işlemlerini tek bir arayüzde yapın." + }, + "mergePdf": { + "name": "PDF Birleştir", + "subtitle": "Birden fazla PDF'yi tek bir dosyada birleştirin. Yer imlerini korur." + }, + "splitPdf": { + "name": "PDF Böl", + "subtitle": "Sayfa aralığını yeni bir PDF olarak çıkarın." + }, + "compressPdf": { + "name": "PDF Sıkıştır", + "subtitle": "PDF dosya boyutunu küçültün." + }, + "pdfEditor": { + "name": "PDF Düzenleyici", + "subtitle": "Açıklama ekleyin, vurgulayın, düzenleyin, yorum yapın, şekil/resim ekleyin, arama yapın ve PDF'leri görüntüleyin." + }, + "jpgToPdf": { + "name": "JPG'den PDF'ye", + "subtitle": "Bir veya daha fazla JPG görselinden PDF oluşturun." + }, + "signPdf": { + "name": "PDF İmzala", + "subtitle": "İmzanızı çizin, yazın veya yükleyin." + }, + "cropPdf": { + "name": "PDF Kırp", + "subtitle": "PDF'nizdeki her sayfanın kenar boşluklarını kırpın." + }, + "extractPages": { + "name": "Sayfaları Çıkar", + "subtitle": "Seçili sayfaları yeni dosyalar olarak kaydedin." + }, + "duplicateOrganize": { + "name": "Çoğalt & Düzenle", + "subtitle": "Sayfaları çoğaltın, yeniden sıralayın ve silin." + }, + "deletePages": { + "name": "Sayfaları Sil", + "subtitle": "Belgenizden belirli sayfaları kaldırın." + }, + "editBookmarks": { + "name": "Yer İşaretlerini Düzenle", + "subtitle": "PDF yer imlerini ekleyin, düzenleyin, içe aktarın, silin ve çıkarın." + }, + "tableOfContents": { + "name": "İçindekiler", + "subtitle": "PDF yer imlerinden bir içindekiler sayfası oluşturun." + }, + "pageNumbers": { + "name": "Sayfa Numaraları", + "subtitle": "Belgenize sayfa numaraları ekleyin." + }, + "addWatermark": { + "name": "Filigran Ekle", + "subtitle": "PDF sayfalarınızın üzerine metin veya görsel damgası ekleyin." + }, + "headerFooter": { + "name": "Üst Bilgi & Alt Bilgi", + "subtitle": "Sayfaların üst ve alt kısmına metin ekleyin." + }, + "invertColors": { + "name": "Renkleri Ters Çevir", + "subtitle": "PDF'niz için \"karanlık mod\" sürümü oluşturun." + }, + "backgroundColor": { + "name": "Arka Plan Rengi", + "subtitle": "PDF'nizin arka plan rengini değiştirin." + }, + "changeTextColor": { + "name": "Metin Rengini Değiştir", + "subtitle": "PDF'nizdeki metnin rengini değiştirin." + }, + "addStamps": { + "name": "Damga Ekle", + "subtitle": "Açıklama araç çubuğunu kullanarak PDF'nize damga ekleyin.", + "usernameLabel": "Kullanıcı Adı", + "usernamePlaceholder": "Adınızı girin (damgalar için)", + "usernameHint": "Bu isim oluşturduğunuz damgalarda görünecektir." + }, + "removeAnnotations": { + "name": "Açıklamaları Kaldır", + "subtitle": "Yorumları, vurguları ve bağlantıları kaldırın." + }, + "pdfFormFiller": { + "name": "PDF Form Doldurucu", + "subtitle": "Formları doğrudan tarayıcıda doldurun. XFA formlarını da destekler." + }, + "createPdfForm": { + "name": "PDF Formu Oluştur", + "subtitle": "Sürükle-bırak metin alanları ile doldurulabilir PDF formları oluşturun." + }, + "removeBlankPages": { + "name": "Boş Sayfaları Kaldır", + "subtitle": "Boş sayfaları otomatik olarak tespit edin ve silin." + }, + "imageToPdf": { + "name": "Görselden PDF'ye", + "subtitle": "JPG, PNG, WebP, BMP, TIFF, SVG, HEIC formatlarını PDF'ye dönüştürün." + }, + "pngToPdf": { + "name": "PNG'den PDF'ye", + "subtitle": "Bir veya daha fazla PNG görselinden PDF oluşturun." + }, + "webpToPdf": { + "name": "WebP'den PDF'ye", + "subtitle": "Bir veya daha fazla WebP görselinden PDF oluşturun." + }, + "svgToPdf": { + "name": "SVG'den PDF'ye", + "subtitle": "Bir veya daha fazla SVG görselinden PDF oluşturun." + }, + "bmpToPdf": { + "name": "BMP'den PDF'ye", + "subtitle": "Bir veya daha fazla BMP görselinden PDF oluşturun." + }, + "heicToPdf": { + "name": "HEIC'den PDF'ye", + "subtitle": "Bir veya daha fazla HEIC görselinden PDF oluşturun." + }, + "tiffToPdf": { + "name": "TIFF'den PDF'ye", + "subtitle": "Bir veya daha fazla TIFF görselinden PDF oluşturun." + }, + "textToPdf": { + "name": "Metinden PDF'ye", + "subtitle": "Düz metin dosyasını PDF'ye dönüştürün." + }, + "jsonToPdf": { + "name": "JSON'dan PDF'ye", + "subtitle": "JSON dosyalarını PDF formatına dönüştürün." + }, + "pdfToJpg": { + "name": "PDF'den JPG'ye", + "subtitle": "Her PDF sayfasını JPG görseline dönüştürün." + }, + "pdfToPng": { + "name": "PDF'den PNG'ye", + "subtitle": "Her PDF sayfasını PNG görseline dönüştürün." + }, + "pdfToWebp": { + "name": "PDF'den WebP'ye", + "subtitle": "Her PDF sayfasını WebP görseline dönüştürün." + }, + "pdfToBmp": { + "name": "PDF'den BMP'ye", + "subtitle": "Her PDF sayfasını BMP görseline dönüştürün." + }, + "pdfToTiff": { + "name": "PDF'den TIFF'e", + "subtitle": "Her PDF sayfasını TIFF görseline dönüştürün." + }, + "pdfToGreyscale": { + "name": "PDF'yi Gri Tonlamaya Çevir", + "subtitle": "Tüm renkleri siyah beyaza çevirin." + }, + "pdfToJson": { + "name": "PDF'den JSON'a", + "subtitle": "PDF dosyalarını JSON formatına dönüştürün." + }, + "ocrPdf": { + "name": "PDF'de OCR", + "subtitle": "PDF'yi aranabilir ve kopyalanabilir hale getirin." + }, + "alternateMix": { + "name": "Sayfaları Karıştır & Birleştir", + "subtitle": "PDF'leri her birinden sayfaları sırayla birleştirin. Yer imlerini korur." + }, + "addAttachments": { + "name": "Ek Dosya Ekle", + "subtitle": "PDF'nize bir veya daha fazla dosya ekleyin." + }, + "extractAttachments": { + "name": "Ek Dosyaları Çıkar", + "subtitle": "PDF'lerden tüm gömülü dosyaları ZIP olarak çıkarın." + }, + "editAttachments": { + "name": "Ek Dosyaları Düzenle", + "subtitle": "PDF'nizdeki ek dosyaları görüntüleyin veya kaldırın." + }, + "dividePages": { + "name": "Sayfaları Böl", + "subtitle": "Sayfaları yatay veya dikey olarak bölün." + }, + "addBlankPage": { + "name": "Boş Sayfa Ekle", + "subtitle": "PDF'nize herhangi bir yerine boş sayfa ekleyin." + }, + "reversePages": { + "name": "Sayfaları Ters Çevir", + "subtitle": "Belgenizdeki tüm sayfaların sırasını tersine çevirin." + }, + "rotatePdf": { + "name": "PDF'yi Döndür", + "subtitle": "Sayfaları 90 derecelik artışlarla döndürün." + }, + "nUpPdf": { + "name": "N'li PDF", + "subtitle": "Birden fazla sayfayı tek bir sayfaya yerleştirin." + }, + "combineToSinglePage": { + "name": "Tek Sayfada Birleştir", + "subtitle": "Tüm sayfaları tek bir sürekli kaydırılabilir sayfada birleştirin." + }, + "viewMetadata": { + "name": "Üst Veriyi Görüntüle", + "subtitle": "PDF'nizin gizli özelliklerini inceleyin." + }, + "editMetadata": { + "name": "Üst Veriyi Düzenle", + "subtitle": "Yazar, başlık ve diğer özellikleri değiştirin." + }, + "pdfsToZip": { + "name": "PDF'leri ZIP Yap", + "subtitle": "Birden fazla PDF dosyasını bir ZIP arşivinde paketleyin." + }, + "comparePdfs": { + "name": "PDF'leri Karşılaştır", + "subtitle": "İki PDF'yi yan yana karşılaştırın." + }, + "posterizePdf": { + "name": "PDF'yi Posta Boyutuna Böl", + "subtitle": "Büyük bir sayfayı birden fazla küçük sayfaya bölün." + }, + "fixPageSize": { + "name": "Sayfa Boyutunu Düzelt", + "subtitle": "Tüm sayfaları standart bir boyuta getirin." + }, + "linearizePdf": { + "name": "PDF'yi Doğrusallaştır", + "subtitle": "Hızlı web görüntüleme için PDF'yi optimize edin." + }, + "pageDimensions": { + "name": "Sayfa Boyutları", + "subtitle": "Sayfa boyutunu, yönlendirmeyi ve birimleri analiz edin." + }, + "removeRestrictions": { + "name": "Kısıtlamaları Kaldır", + "subtitle": "Dijital olarak imzalanmış PDF dosyalarıyla ilişkili şifre korumasını ve güvenlik kısıtlamalarını kaldırın." + }, + "repairPdf": { + "name": "PDF'yi Onar", + "subtitle": "Bozulmuş veya hasarlı PDF dosyalarından veri kurtarın." + }, + "encryptPdf": { + "name": "PDF'yi Şifrele", + "subtitle": "PDF'nizi şifre ekleyerek koruyun." + }, + "sanitizePdf": { + "name": "PDF'yi Temizle", + "subtitle": "Üst verileri, açıklamaları, betikleri ve daha fazlasını kaldırın." + }, + "decryptPdf": { + "name": "PDF'nin Şifresini Çöz", + "subtitle": "Şifre korumasını kaldırarak PDF'nin kilidini açın." + }, + "flattenPdf": { + "name": "PDF'yi Düzleştir", + "subtitle": "Form alanlarını ve açıklamaları düzenlenemez hale getirin." + }, + "removeMetadata": { + "name": "Üst Veriyi Kaldır", + "subtitle": "PDF'nizdeki gizli verileri temizleyin." + }, + "changePermissions": { + "name": "İzinleri Değiştir", + "subtitle": "Bir PDF üzerindeki kullanıcı izinlerini ayarlayın veya değiştirin." + }, + "emailToPdf": { + "name": "E-posta'dan PDF'ye", + "subtitle": "E-posta dosyalarını (EML, MSG) PDF formatına dönüştürün. Outlook dışa aktarmalarını ve standart e-posta formatlarını destekler.", + "acceptedFormats": "EML, MSG Dosyaları", + "convertButton": "PDF'ye Dönüştür" + }, + "fontToOutline": { + "name": "Yazı Tipi Çerçeveye Dönüştür", + "subtitle": "Tüm yazı tiplerini vektör çerçevelere dönüştürün, tüm cihazlarda tutarlı görüntü için." + }, + "deskewPdf": { + "name": "PDF Eğriliğini Düzelt", + "subtitle": "OpenCV kullanarak eğik taranmış sayfaları otomatik olarak düzeltin." + }, + "rotateCustom": { + "name": "Rotate by Custom Degrees", + "subtitle": "Rotate pages by any custom angle." + }, + "odtToPdf": { + "name": "ODT to PDF", + "subtitle": "Convert OpenDocument Text files to PDF format. Supports multiple files.", + "acceptedFormats": "ODT files", + "convertButton": "Convert to PDF" + }, + "csvToPdf": { + "name": "CSV to PDF", + "subtitle": "Convert CSV spreadsheet files to PDF format. Supports multiple files.", + "acceptedFormats": "CSV files", + "convertButton": "Convert to PDF" + }, + "rtfToPdf": { + "name": "RTF to PDF", + "subtitle": "Convert Rich Text Format documents to PDF. Supports multiple files.", + "acceptedFormats": "RTF files", + "convertButton": "Convert to PDF" + }, + "wordToPdf": { + "name": "Word to PDF", + "subtitle": "Convert Word documents (DOCX, DOC, ODT, RTF) to PDF format. Supports multiple files.", + "acceptedFormats": "DOCX, DOC, ODT, RTF files", + "convertButton": "Convert to PDF" + }, + "excelToPdf": { + "name": "Excel to PDF", + "subtitle": "Convert Excel spreadsheets (XLSX, XLS, ODS, CSV) to PDF format. Supports multiple files.", + "acceptedFormats": "XLSX, XLS, ODS, CSV files", + "convertButton": "Convert to PDF" + }, + "powerpointToPdf": { + "name": "PowerPoint to PDF", + "subtitle": "Convert PowerPoint presentations (PPTX, PPT, ODP) to PDF format. Supports multiple files.", + "acceptedFormats": "PPTX, PPT, ODP files", + "convertButton": "Convert to PDF" + }, + "markdownToPdf": { + "name": "Markdown to PDF", + "subtitle": "Write or paste Markdown and export it as a beautifully formatted PDF.", + "paneMarkdown": "Markdown", + "panePreview": "Preview", + "btnUpload": "Upload", + "btnSyncScroll": "Sync Scroll", + "btnSettings": "Settings", + "btnExportPdf": "Export PDF", + "settingsTitle": "Markdown Settings", + "settingsPreset": "Preset", + "presetDefault": "Default (GFM-like)", + "presetCommonmark": "CommonMark (strict)", + "presetZero": "Minimal (no features)", + "settingsOptions": "Markdown Options", + "optAllowHtml": "Allow HTML tags", + "optBreaks": "Convert newlines to
", + "optLinkify": "Auto-convert URLs to links", + "optTypographer": "Typographer (smart quotes, etc.)" + }, + "pdfBooklet": { + "name": "PDF Booklet", + "subtitle": "Rearrange pages for double-sided booklet printing. Fold and staple to create a booklet.", + "howItWorks": "How it works:", + "step1": "Upload a PDF file.", + "step2": "Pages will be rearranged in booklet order.", + "step3": "Print double-sided, flip on short edge, fold and staple.", + "paperSize": "Paper Size", + "orientation": "Orientation", + "portrait": "Portrait", + "landscape": "Landscape", + "pagesPerSheet": "Pages per Sheet", + "createBooklet": "Create Booklet", + "processing": "Processing...", + "pageCount": "Page count will be padded to multiple of 4 if needed." + }, + "xpsToPdf": { + "name": "XPS to PDF", + "subtitle": "Convert XPS/OXPS documents to PDF format. Supports multiple files.", + "acceptedFormats": "XPS, OXPS files", + "convertButton": "Convert to PDF" + }, + "mobiToPdf": { + "name": "MOBI to PDF", + "subtitle": "Convert MOBI e-books to PDF format. Supports multiple files.", + "acceptedFormats": "MOBI files", + "convertButton": "Convert to PDF" + }, + "epubToPdf": { + "name": "EPUB to PDF", + "subtitle": "Convert EPUB e-books to PDF format. Supports multiple files.", + "acceptedFormats": "EPUB files", + "convertButton": "Convert to PDF" + }, + "fb2ToPdf": { + "name": "FB2 to PDF", + "subtitle": "Convert FictionBook (FB2) e-books to PDF format. Supports multiple files.", + "acceptedFormats": "FB2 files", + "convertButton": "Convert to PDF" + }, + "cbzToPdf": { + "name": "CBZ to PDF", + "subtitle": "Convert comic book archives (CBZ/CBR) to PDF format. Supports multiple files.", + "acceptedFormats": "CBZ, CBR files", + "convertButton": "Convert to PDF" + }, + "wpdToPdf": { + "name": "WPD to PDF", + "subtitle": "Convert WordPerfect documents (WPD) to PDF format. Supports multiple files.", + "acceptedFormats": "WPD files", + "convertButton": "Convert to PDF" + }, + "wpsToPdf": { + "name": "WPS to PDF", + "subtitle": "Convert WPS Office documents to PDF format. Supports multiple files.", + "acceptedFormats": "WPS files", + "convertButton": "Convert to PDF" + }, + "xmlToPdf": { + "name": "XML to PDF", + "subtitle": "Convert XML documents to PDF format. Supports multiple files.", + "acceptedFormats": "XML files", + "convertButton": "Convert to PDF" + }, + "pagesToPdf": { + "name": "Pages to PDF", + "subtitle": "Convert Apple Pages documents to PDF format. Supports multiple files.", + "acceptedFormats": "Pages files", + "convertButton": "Convert to PDF" + }, + "odgToPdf": { + "name": "ODG to PDF", + "subtitle": "Convert OpenDocument Graphics (ODG) files to PDF format. Supports multiple files.", + "acceptedFormats": "ODG files", + "convertButton": "Convert to PDF" + }, + "odsToPdf": { + "name": "ODS to PDF", + "subtitle": "Convert OpenDocument Spreadsheet (ODS) files to PDF format. Supports multiple files.", + "acceptedFormats": "ODS files", + "convertButton": "Convert to PDF" + }, + "odpToPdf": { + "name": "ODP to PDF", + "subtitle": "Convert OpenDocument Presentation (ODP) files to PDF format. Supports multiple files.", + "acceptedFormats": "ODP files", + "convertButton": "Convert to PDF" + }, + "pubToPdf": { + "name": "PUB to PDF", + "subtitle": "Convert Microsoft Publisher (PUB) files to PDF format. Supports multiple files.", + "acceptedFormats": "PUB files", + "convertButton": "Convert to PDF" + }, + "vsdToPdf": { + "name": "VSD to PDF", + "subtitle": "Convert Microsoft Visio (VSD, VSDX) files to PDF format. Supports multiple files.", + "acceptedFormats": "VSD, VSDX files", + "convertButton": "Convert to PDF" + }, + "psdToPdf": { + "name": "PSD to PDF", + "subtitle": "Convert Adobe Photoshop (PSD) files to PDF format. Supports multiple files.", + "acceptedFormats": "PSD files", + "convertButton": "Convert to PDF" + }, + "pdfToSvg": { + "name": "PDF to SVG", + "subtitle": "Convert each page of a PDF file into a scalable vector graphic (SVG) for perfect quality at any size." + }, + "extractTables": { + "name": "Extract PDF Tables", + "subtitle": "Extract tables from PDF files and export as CSV, JSON, or Markdown." + }, + "pdfToCsv": { + "name": "PDF to CSV", + "subtitle": "Extract tables from PDF and convert to CSV format." + }, + "pdfToExcel": { + "name": "PDF to Excel", + "subtitle": "Extract tables from PDF and convert to Excel (XLSX) format." + }, + "pdfToText": { + "name": "PDF to Text", + "subtitle": "Extract text from PDF files and save as plain text (.txt). Supports multiple files.", + "note": "This tool works ONLY with digitally created PDFs. For scanned documents or image-based PDFs, use our OCR PDF tool instead.", + "convertButton": "Extract Text" + }, + "digitalSignPdf": { + "name": "Digital Signature PDF", + "pageTitle": "Digital Signature PDF - Add Cryptographic Signature | BentoPDF", + "subtitle": "Add a cryptographic digital signature to your PDF using X.509 certificates. Supports PKCS#12 (.pfx, .p12) and PEM formats. Your private key never leaves your browser.", + "certificateSection": "Certificate", + "uploadCert": "Upload certificate (.pfx, .p12)", + "certPassword": "Certificate Password", + "certPasswordPlaceholder": "Enter certificate password", + "certInfo": "Certificate Information", + "certSubject": "Subject", + "certIssuer": "Issuer", + "certValidity": "Valid", + "signatureDetails": "Signature Details (Optional)", + "reason": "Reason", + "reasonPlaceholder": "e.g., I approve this document", + "location": "Location", + "locationPlaceholder": "e.g., New York, USA", + "contactInfo": "Contact Info", + "contactPlaceholder": "e.g., email@example.com", + "applySignature": "Apply Digital Signature", + "successMessage": "PDF signed successfully! The signature can be verified in any PDF reader." + }, + "validateSignaturePdf": { + "name": "Validate PDF Signature", + "pageTitle": "Validate PDF Signature - Verify Digital Signatures | BentoPDF", + "subtitle": "Verify digital signatures in your PDF files. Check certificate validity, view signer details, and confirm document integrity. All processing happens in your browser." + } +} diff --git a/public/locales/vi/common.json b/public/locales/vi/common.json index 6a12390..1ebaa40 100644 --- a/public/locales/vi/common.json +++ b/public/locales/vi/common.json @@ -1,318 +1,323 @@ { - "nav": { - "home": "Trang chủ", - "about": "Giới thiệu", - "contact": "Liên hệ", - "licensing": "Giấy phép", - "allTools": "Tất cả công cụ", - "openMainMenu": "Mở menu chính", - "language": "Ngôn ngữ" + "nav": { + "home": "Trang chủ", + "about": "Giới thiệu", + "contact": "Liên hệ", + "licensing": "Giấy phép", + "allTools": "Tất cả công cụ", + "openMainMenu": "Mở menu chính", + "language": "Ngôn ngữ" + }, + "donation": { + "message": "Bạn yêu thích BentoPDF? Hãy giúp chúng tôi giữ nó miễn phí và mã nguồn mở!", + "button": "Quyên góp" + }, + "hero": { + "title": "Bộ công cụ", + "pdfToolkit": "PDF", + "builtForPrivacy": "an toàn và riêng tư", + "noSignups": "Không cần đăng ký", + "unlimitedUse": "Sử dụng không giới hạn", + "worksOffline": "Hoạt động offline", + "startUsing": "Bắt đầu sử dụng ngay" + }, + "usedBy": { + "title": "Được sử dụng bởi các công ty và những người làm việc tại" + }, + "features": { + "title": "Tại sao chọn", + "bentoPdf": "BentoPDF?", + "noSignup": { + "title": "Không cần đăng ký", + "description": "Bắt đầu ngay lập tức, không cần tài khoản hay email." }, - "hero": { - "title": "Bộ công cụ", - "pdfToolkit": "PDF", - "builtForPrivacy": "an toàn và riêng tư", - "noSignups": "Không cần đăng ký", - "unlimitedUse": "Sử dụng không giới hạn", - "worksOffline": "Hoạt động offline", - "startUsing": "Bắt đầu sử dụng ngay" + "noUploads": { + "title": "Không tải lên", + "description": "100% xử lý phía máy khách, tệp của bạn không bao giờ rời khỏi thiết bị." }, - "usedBy": { - "title": "Được sử dụng bởi các công ty và những người làm việc tại" + "foreverFree": { + "title": "Miễn phí mãi mãi", + "description": "Tất cả công cụ, không dùng thử, không có tường phí." }, - "features": { - "title": "Tại sao chọn", - "bentoPdf": "BentoPDF?", - "noSignup": { - "title": "Không cần đăng ký", - "description": "Bắt đầu ngay lập tức, không cần tài khoản hay email." - }, - "noUploads": { - "title": "Không tải lên", - "description": "100% xử lý phía máy khách, tệp của bạn không bao giờ rời khỏi thiết bị." - }, - "foreverFree": { - "title": "Miễn phí mãi mãi", - "description": "Tất cả công cụ, không dùng thử, không có tường phí." - }, - "noLimits": { - "title": "Không giới hạn", - "description": "Sử dụng bao nhiêu tùy thích, không có giới hạn ẩn." - }, - "batchProcessing": { - "title": "Xử lý hàng loạt", - "description": "Xử lý không giới hạn PDF trong một lần." - }, - "lightningFast": { - "title": "Cực kỳ nhanh", - "description": "Xử lý PDF ngay lập tức, không cần chờ đợi hay trì hoãn." - } + "noLimits": { + "title": "Không giới hạn", + "description": "Sử dụng bao nhiêu tùy thích, không có giới hạn ẩn." }, - "tools": { - "title": "Bắt đầu với", - "toolsLabel": "Công cụ", - "subtitle": "Nhấp vào một công cụ để mở trình tải tệp lên", - "searchPlaceholder": "Tìm kiếm công cụ (ví dụ: 'chia', 'sắp xếp'...)", - "backToTools": "Quay lại Công cụ" + "batchProcessing": { + "title": "Xử lý hàng loạt", + "description": "Xử lý không giới hạn PDF trong một lần." }, - "upload": { - "clickToSelect": "Nhấp để chọn tệp", - "orDragAndDrop": "hoặc kéo và thả", - "pdfOrImages": "PDF hoặc Hình ảnh", - "filesNeverLeave": "Tệp của bạn không bao giờ rời khỏi thiết bị.", - "addMore": "Thêm tệp", - "clearAll": "Xóa tất cả" - }, - "loader": { - "processing": "Đang xử lý..." - }, - "alert": { - "title": "Thông báo", - "ok": "OK" - }, - "preview": { - "title": "Xem trước tài liệu", - "downloadAsPdf": "Tải xuống dưới dạng PDF", - "close": "Đóng" - }, - "settings": { - "title": "Cài đặt", - "shortcuts": "Phím tắt", - "preferences": "Tùy chọn", - "displayPreferences": "Tùy chọn hiển thị", - "searchShortcuts": "Tìm kiếm phím tắt...", - "shortcutsInfo": "Nhấn và giữ phím để đặt phím tắt. Thay đổi được lưu tự động.", - "shortcutsWarning": "⚠️ Tránh các phím tắt trình duyệt phổ biến (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N, v.v.) vì chúng có thể không hoạt động đáng tin cậy.", - "import": "Nhập", - "export": "Xuất", - "resetToDefaults": "Đặt lại về mặc định", - "fullWidthMode": "Chế độ toàn chiều rộng", - "fullWidthDescription": "Sử dụng toàn bộ chiều rộng màn hình cho tất cả công cụ thay vì container căn giữa", - "settingsAutoSaved": "Cài đặt được lưu tự động", - "clickToSet": "Nhấp để đặt", - "pressKeys": "Nhấn phím...", - "warnings": { - "alreadyInUse": "Phím tắt đã được sử dụng", - "assignedTo": "đã được gán cho:", - "chooseDifferent": "Vui lòng chọn một phím tắt khác.", - "reserved": "Cảnh báo phím tắt dành riêng", - "commonlyUsed": "thường được sử dụng cho:", - "unreliable": "Phím tắt này có thể không hoạt động đáng tin cậy hoặc có thể xung đột với hành vi trình duyệt/hệ thống.", - "useAnyway": "Bạn có muốn sử dụng nó không?", - "resetTitle": "Đặt lại phím tắt", - "resetMessage": "Bạn có chắc chắn muốn đặt lại tất cả phím tắt về mặc định?

Hành động này không thể hoàn tác.", - "importSuccessTitle": "Nhập thành công", - "importSuccessMessage": "Đã nhập phím tắt thành công!", - "importFailTitle": "Nhập thất bại", - "importFailMessage": "Không thể nhập phím tắt. Định dạng tệp không hợp lệ." - } - }, - "warning": { - "title": "Cảnh báo", - "cancel": "Hủy", - "proceed": "Tiếp tục" - }, - "compliance": { - "title": "Dữ liệu của bạn không bao giờ rời khỏi thiết bị", - "weKeep": "Chúng tôi giữ", - "yourInfoSafe": "thông tin của bạn an toàn", - "byFollowingStandards": "bằng cách tuân theo các tiêu chuẩn bảo mật toàn cầu.", - "processingLocal": "Tất cả quá trình xử lý diễn ra cục bộ trên thiết bị của bạn.", - "gdpr": { - "title": "Tuân thủ GDPR", - "description": "Bảo vệ dữ liệu cá nhân và quyền riêng tư của các cá nhân trong Liên minh Châu Âu." - }, - "ccpa": { - "title": "Tuân thủ CCPA", - "description": "Trao quyền cho cư dân California về cách thông tin cá nhân của họ được thu thập, sử dụng và chia sẻ." - }, - "hipaa": { - "title": "Tuân thủ HIPAA", - "description": "Đặt ra các biện pháp bảo vệ để xử lý thông tin sức khỏe nhạy cảm trong hệ thống chăm sóc sức khỏe Hoa Kỳ." - } - }, - "faq": { - "title": "Câu hỏi", - "questions": "Thường gặp", - "isFree": { - "question": "BentoPDF có thực sự miễn phí không?", - "answer": "Có, hoàn toàn miễn phí. Tất cả các công cụ trên BentoPDF đều 100% miễn phí sử dụng, không giới hạn tệp, không cần đăng ký và không có watermark. Chúng tôi tin rằng mọi người đều xứng đáng được tiếp cận với các công cụ PDF đơn giản, mạnh mẽ mà không có tường phí." - }, - "areFilesSecure": { - "question": "Tệp của tôi có an toàn không? Chúng được xử lý ở đâu?", - "answer": "Tệp của bạn an toàn nhất có thể vì chúng không bao giờ rời khỏi máy tính của bạn. Tất cả quá trình xử lý diễn ra trực tiếp trong trình duyệt web của bạn (phía máy khách). Chúng tôi không bao giờ tải tệp của bạn lên máy chủ, vì vậy bạn duy trì quyền riêng tư và kiểm soát hoàn toàn đối với tài liệu của mình." - }, - "platforms": { - "question": "Nó có hoạt động trên Mac, Windows và Mobile không?", - "answer": "Có! Vì BentoPDF chạy hoàn toàn trong trình duyệt của bạn, nó hoạt động trên bất kỳ hệ điều hành nào có trình duyệt web hiện đại, bao gồm Windows, macOS, Linux, iOS và Android." - }, - "gdprCompliant": { - "question": "BentoPDF có tuân thủ GDPR không?", - "answer": "Có. BentoPDF hoàn toàn tuân thủ GDPR. Vì tất cả quá trình xử lý tệp diễn ra cục bộ trong trình duyệt của bạn và chúng tôi không bao giờ thu thập hoặc truyền tệp của bạn đến bất kỳ máy chủ nào, chúng tôi không có quyền truy cập vào dữ liệu của bạn. Điều này đảm bảo bạn luôn kiểm soát tài liệu của mình." - }, - "dataStorage": { - "question": "Bạn có lưu trữ hoặc theo dõi bất kỳ tệp nào của tôi không?", - "answer": "Không. Chúng tôi không bao giờ lưu trữ, theo dõi hoặc ghi nhật ký tệp của bạn. Mọi thứ bạn làm trên BentoPDF diễn ra trong bộ nhớ trình duyệt của bạn và biến mất khi bạn đóng trang. Không có tải lên, không có nhật ký lịch sử và không có máy chủ liên quan." - }, - "different": { - "question": "Điều gì làm cho BentoPDF khác biệt so với các công cụ PDF khác?", - "answer": "Hầu hết các công cụ PDF tải tệp của bạn lên máy chủ để xử lý. BentoPDF không bao giờ làm điều đó. Chúng tôi sử dụng công nghệ web hiện đại, an toàn để xử lý tệp của bạn trực tiếp trong trình duyệt. Điều này có nghĩa là hiệu suất nhanh hơn, quyền riêng tư mạnh mẽ hơn và hoàn toàn yên tâm." - }, - "browserBased": { - "question": "Xử lý dựa trên trình duyệt giữ tôi an toàn như thế nào?", - "answer": "Bằng cách chạy hoàn toàn bên trong trình duyệt của bạn, BentoPDF đảm bảo rằng tệp của bạn không bao giờ rời khỏi thiết bị. Điều này loại bỏ các rủi ro về hack máy chủ, vi phạm dữ liệu hoặc truy cập trái phép. Tệp của bạn vẫn thuộc về bạn—luôn luôn." - }, - "analytics": { - "question": "Bạn có sử dụng cookie hoặc phân tích để theo dõi tôi không?", - "answer": "Chúng tôi quan tâm đến quyền riêng tư của bạn. BentoPDF không theo dõi thông tin cá nhân. Chúng tôi chỉ sử dụng Simple Analytics để xem số lượt truy cập ẩn danh. Điều này có nghĩa là chúng tôi có thể biết có bao nhiêu người dùng truy cập trang web của chúng tôi, nhưng chúng tôi không bao giờ biết bạn là ai. Simple Analytics hoàn toàn tuân thủ GDPR và tôn trọng quyền riêng tư của bạn." - } - }, - "testimonials": { - "title": "Người dùng", - "users": "của chúng tôi", - "say": "nói gì" - }, - "support": { - "title": "Thích công việc của tôi?", - "description": "BentoPDF là một dự án đam mê, được xây dựng để cung cấp bộ công cụ PDF miễn phí, riêng tư và mạnh mẽ cho mọi người. Nếu bạn thấy nó hữu ích, hãy cân nhắc hỗ trợ phát triển của nó. Mỗi ly cà phê đều giúp ích!", - "buyMeCoffee": "Mua cho tôi một ly cà phê" - }, - "footer": { - "copyright": "© 2025 BentoPDF. Bảo lưu mọi quyền.", - "version": "Phiên bản", - "company": "Công ty", - "aboutUs": "Về chúng tôi", - "faqLink": "FAQ", - "contactUs": "Liên hệ", - "legal": "Pháp lý", - "termsAndConditions": "Điều khoản và Điều kiện", - "privacyPolicy": "Chính sách Bảo mật", - "followUs": "Theo dõi chúng tôi" - }, - "merge": { - "title": "Gộp PDF", - "description": "Kết hợp toàn bộ tệp hoặc chọn các trang cụ thể để gộp thành tài liệu mới.", - "fileMode": "Chế độ tệp", - "pageMode": "Chế độ trang", - "howItWorks": "Cách hoạt động:", - "fileModeInstructions": [ - "Nhấp và kéo biểu tượng để thay đổi thứ tự các tệp.", - "Trong hộp \"Trang\" cho mỗi tệp, bạn có thể chỉ định phạm vi (ví dụ: \"1-3, 5\") để chỉ gộp những trang đó.", - "Để trống hộp \"Trang\" để bao gồm tất cả các trang từ tệp đó." - ], - "pageModeInstructions": [ - "Tất cả các trang từ PDF đã tải lên của bạn được hiển thị bên dưới.", - "Chỉ cần kéo và thả các hình thu nhỏ trang riêng lẻ để tạo thứ tự chính xác bạn muốn cho tệp mới của mình." - ], - "mergePdfs": "Gộp PDF" - }, - "common": { - "page": "Trang", - "pages": "Trang", - "of": "của", - "download": "Tải xuống", - "cancel": "Hủy", - "save": "Lưu", - "delete": "Xóa", - "edit": "Chỉnh sửa", - "add": "Thêm", - "remove": "Xóa", - "loading": "Đang tải...", - "error": "Lỗi", - "success": "Thành công", - "file": "Tệp", - "files": "Tệp" - }, - "about": { - "hero": { - "title": "Chúng tôi tin rằng công cụ PDF nên", - "subtitle": "nhanh, riêng tư và miễn phí.", - "noCompromises": "Không thỏa hiệp." - }, - "mission": { - "title": "Sứ mệnh của chúng tôi", - "description": "Cung cấp bộ công cụ PDF toàn diện nhất tôn trọng quyền riêng tư của bạn và không bao giờ yêu cầu thanh toán. Chúng tôi tin rằng các công cụ tài liệu thiết yếu nên có thể truy cập được cho mọi người, ở mọi nơi, không có rào cản." - }, - "philosophy": { - "label": "Triết lý cốt lõi của chúng tôi", - "title": "Quyền riêng tư trước tiên. Luôn luôn.", - "description": "Trong thời đại mà dữ liệu là hàng hóa, chúng tôi có cách tiếp cận khác. Tất cả quá trình xử lý cho các công cụ Bentopdf diễn ra cục bộ trong trình duyệt của bạn. Điều này có nghĩa là tệp của bạn không bao giờ chạm vào máy chủ của chúng tôi, chúng tôi không bao giờ thấy tài liệu của bạn và chúng tôi không theo dõi những gì bạn làm. Tài liệu của bạn vẫn hoàn toàn và rõ ràng là riêng tư. Đó không chỉ là một tính năng; đó là nền tảng của chúng tôi." - }, - "whyBentopdf": { - "title": "Tại sao chọn", - "speed": { - "title": "Được xây dựng cho tốc độ", - "description": "Không cần chờ tải lên hoặc tải xuống lên máy chủ. Bằng cách xử lý tệp trực tiếp trong trình duyệt của bạn bằng công nghệ web hiện đại như WebAssembly, chúng tôi cung cấp tốc độ vô song cho tất cả các công cụ của chúng tôi." - }, - "free": { - "title": "Hoàn toàn miễn phí", - "description": "Không dùng thử, không đăng ký, không phí ẩn và không có tính năng \"premium\" bị giữ lại. Chúng tôi tin rằng các công cụ PDF mạnh mẽ nên là tiện ích công cộng, không phải trung tâm lợi nhuận." - }, - "noAccount": { - "title": "Không cần tài khoản", - "description": "Bắt đầu sử dụng bất kỳ công cụ nào ngay lập tức. Chúng tôi không cần email, mật khẩu hoặc bất kỳ thông tin cá nhân nào của bạn. Quy trình làm việc của bạn nên không ma sát và ẩn danh." - }, - "openSource": { - "title": "Tinh thần mã nguồn mở", - "description": "Được xây dựng với tinh thần minh bạch. Chúng tôi tận dụng các thư viện mã nguồn mở tuyệt vời như PDF-lib và PDF.js, và tin vào nỗ lực do cộng đồng thúc đẩy để làm cho các công cụ mạnh mẽ có thể truy cập được cho mọi người." - } - }, - "cta": { - "title": "Sẵn sàng bắt đầu?", - "description": "Tham gia cùng hàng nghìn người dùng tin tưởng Bentopdf cho nhu cầu tài liệu hàng ngày của họ. Trải nghiệm sự khác biệt mà quyền riêng tư và hiệu suất có thể tạo ra.", - "button": "Khám phá tất cả công cụ" - } - }, - "contact": { - "title": "Liên hệ", - "subtitle": "Chúng tôi rất muốn nghe từ bạn. Cho dù bạn có câu hỏi, phản hồi hay yêu cầu tính năng, vui lòng đừng ngần ngại liên hệ.", - "email": "Bạn có thể liên hệ trực tiếp với chúng tôi qua email tại:" - }, - "licensing": { - "title": "Giấy phép cho", - "subtitle": "Chọn giấy phép phù hợp với nhu cầu của bạn." - }, - "multiTool": { - "uploadPdfs": "Tải lên PDF", - "upload": "Tải lên", - "addBlankPage": "Thêm trang trống", - "edit": "Chỉnh sửa:", - "undo": "Hoàn tác", - "redo": "Làm lại", - "reset": "Đặt lại", - "selection": "Chọn:", - "selectAll": "Chọn tất cả", - "deselectAll": "Bỏ chọn tất cả", - "rotate": "Xoay:", - "rotateLeft": "Trái", - "rotateRight": "Phải", - "transform": "Biến đổi:", - "duplicate": "Nhân bản", - "split": "Chia", - "clear": "Xóa:", - "delete": "Xóa", - "download": "Tải xuống:", - "downloadSelected": "Tải xuống đã chọn", - "exportPdf": "Xuất PDF", - "uploadPdfFiles": "Chọn tệp PDF", - "dragAndDrop": "Kéo và thả tệp PDF vào đây, hoặc nhấp để chọn", - "selectFiles": "Chọn tệp", - "renderingPages": "Đang kết xuất trang...", - "actions": { - "duplicatePage": "Nhân bản trang này", - "deletePage": "Xóa trang này", - "insertPdf": "Chèn PDF sau trang này", - "toggleSplit": "Bật/tắt chia sau trang này" - }, - "pleaseWait": "Vui lòng đợi", - "pagesRendering": "Các trang vẫn đang được kết xuất. Vui lòng đợi...", - "noPagesSelected": "Chưa chọn trang nào", - "selectOnePage": "Vui lòng chọn ít nhất một trang để tải xuống.", - "noPages": "Không có trang", - "noPagesToExport": "Không có trang nào để xuất.", - "renderingTitle": "Đang kết xuất xem trước trang", - "errorRendering": "Không thể kết xuất hình thu nhỏ trang", - "error": "Lỗi", - "failedToLoad": "Không thể tải" + "lightningFast": { + "title": "Cực kỳ nhanh", + "description": "Xử lý PDF ngay lập tức, không cần chờ đợi hay trì hoãn." } -} \ No newline at end of file + }, + "tools": { + "title": "Bắt đầu với", + "toolsLabel": "Công cụ", + "subtitle": "Nhấp vào một công cụ để mở trình tải tệp lên", + "searchPlaceholder": "Tìm kiếm công cụ (ví dụ: 'chia', 'sắp xếp'...)", + "backToTools": "Quay lại Công cụ", + "firstLoadNotice": "Lần tải đầu tiên sẽ mất một chút thời gian vì chúng tôi đang tải xuống công cụ chuyển đổi. Sau đó, mọi lần tải sẽ ngay lập tức." + }, + "upload": { + "clickToSelect": "Nhấp để chọn tệp", + "orDragAndDrop": "hoặc kéo và thả", + "pdfOrImages": "PDF hoặc Hình ảnh", + "filesNeverLeave": "Tệp của bạn không bao giờ rời khỏi thiết bị.", + "addMore": "Thêm tệp", + "clearAll": "Xóa tất cả" + }, + "loader": { + "processing": "Đang xử lý..." + }, + "alert": { + "title": "Thông báo", + "ok": "OK" + }, + "preview": { + "title": "Xem trước tài liệu", + "downloadAsPdf": "Tải xuống dưới dạng PDF", + "close": "Đóng" + }, + "settings": { + "title": "Cài đặt", + "shortcuts": "Phím tắt", + "preferences": "Tùy chọn", + "displayPreferences": "Tùy chọn hiển thị", + "searchShortcuts": "Tìm kiếm phím tắt...", + "shortcutsInfo": "Nhấn và giữ phím để đặt phím tắt. Thay đổi được lưu tự động.", + "shortcutsWarning": "⚠️ Tránh các phím tắt trình duyệt phổ biến (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N, v.v.) vì chúng có thể không hoạt động đáng tin cậy.", + "import": "Nhập", + "export": "Xuất", + "resetToDefaults": "Đặt lại về mặc định", + "fullWidthMode": "Chế độ toàn chiều rộng", + "fullWidthDescription": "Sử dụng toàn bộ chiều rộng màn hình cho tất cả công cụ thay vì container căn giữa", + "settingsAutoSaved": "Cài đặt được lưu tự động", + "clickToSet": "Nhấp để đặt", + "pressKeys": "Nhấn phím...", + "warnings": { + "alreadyInUse": "Phím tắt đã được sử dụng", + "assignedTo": "đã được gán cho:", + "chooseDifferent": "Vui lòng chọn một phím tắt khác.", + "reserved": "Cảnh báo phím tắt dành riêng", + "commonlyUsed": "thường được sử dụng cho:", + "unreliable": "Phím tắt này có thể không hoạt động đáng tin cậy hoặc có thể xung đột với hành vi trình duyệt/hệ thống.", + "useAnyway": "Bạn có muốn sử dụng nó không?", + "resetTitle": "Đặt lại phím tắt", + "resetMessage": "Bạn có chắc chắn muốn đặt lại tất cả phím tắt về mặc định?

Hành động này không thể hoàn tác.", + "importSuccessTitle": "Nhập thành công", + "importSuccessMessage": "Đã nhập phím tắt thành công!", + "importFailTitle": "Nhập thất bại", + "importFailMessage": "Không thể nhập phím tắt. Định dạng tệp không hợp lệ." + } + }, + "warning": { + "title": "Cảnh báo", + "cancel": "Hủy", + "proceed": "Tiếp tục" + }, + "compliance": { + "title": "Dữ liệu của bạn không bao giờ rời khỏi thiết bị", + "weKeep": "Chúng tôi giữ", + "yourInfoSafe": "thông tin của bạn an toàn", + "byFollowingStandards": "bằng cách tuân theo các tiêu chuẩn bảo mật toàn cầu.", + "processingLocal": "Tất cả quá trình xử lý diễn ra cục bộ trên thiết bị của bạn.", + "gdpr": { + "title": "Tuân thủ GDPR", + "description": "Bảo vệ dữ liệu cá nhân và quyền riêng tư của các cá nhân trong Liên minh Châu Âu." + }, + "ccpa": { + "title": "Tuân thủ CCPA", + "description": "Trao quyền cho cư dân California về cách thông tin cá nhân của họ được thu thập, sử dụng và chia sẻ." + }, + "hipaa": { + "title": "Tuân thủ HIPAA", + "description": "Đặt ra các biện pháp bảo vệ để xử lý thông tin sức khỏe nhạy cảm trong hệ thống chăm sóc sức khỏe Hoa Kỳ." + } + }, + "faq": { + "title": "Câu hỏi", + "questions": "Thường gặp", + "isFree": { + "question": "BentoPDF có thực sự miễn phí không?", + "answer": "Có, hoàn toàn miễn phí. Tất cả các công cụ trên BentoPDF đều 100% miễn phí sử dụng, không giới hạn tệp, không cần đăng ký và không có watermark. Chúng tôi tin rằng mọi người đều xứng đáng được tiếp cận với các công cụ PDF đơn giản, mạnh mẽ mà không có tường phí." + }, + "areFilesSecure": { + "question": "Tệp của tôi có an toàn không? Chúng được xử lý ở đâu?", + "answer": "Tệp của bạn an toàn nhất có thể vì chúng không bao giờ rời khỏi máy tính của bạn. Tất cả quá trình xử lý diễn ra trực tiếp trong trình duyệt web của bạn (phía máy khách). Chúng tôi không bao giờ tải tệp của bạn lên máy chủ, vì vậy bạn duy trì quyền riêng tư và kiểm soát hoàn toàn đối với tài liệu của mình." + }, + "platforms": { + "question": "Nó có hoạt động trên Mac, Windows và Mobile không?", + "answer": "Có! Vì BentoPDF chạy hoàn toàn trong trình duyệt của bạn, nó hoạt động trên bất kỳ hệ điều hành nào có trình duyệt web hiện đại, bao gồm Windows, macOS, Linux, iOS và Android." + }, + "gdprCompliant": { + "question": "BentoPDF có tuân thủ GDPR không?", + "answer": "Có. BentoPDF hoàn toàn tuân thủ GDPR. Vì tất cả quá trình xử lý tệp diễn ra cục bộ trong trình duyệt của bạn và chúng tôi không bao giờ thu thập hoặc truyền tệp của bạn đến bất kỳ máy chủ nào, chúng tôi không có quyền truy cập vào dữ liệu của bạn. Điều này đảm bảo bạn luôn kiểm soát tài liệu của mình." + }, + "dataStorage": { + "question": "Bạn có lưu trữ hoặc theo dõi bất kỳ tệp nào của tôi không?", + "answer": "Không. Chúng tôi không bao giờ lưu trữ, theo dõi hoặc ghi nhật ký tệp của bạn. Mọi thứ bạn làm trên BentoPDF diễn ra trong bộ nhớ trình duyệt của bạn và biến mất khi bạn đóng trang. Không có tải lên, không có nhật ký lịch sử và không có máy chủ liên quan." + }, + "different": { + "question": "Điều gì làm cho BentoPDF khác biệt so với các công cụ PDF khác?", + "answer": "Hầu hết các công cụ PDF tải tệp của bạn lên máy chủ để xử lý. BentoPDF không bao giờ làm điều đó. Chúng tôi sử dụng công nghệ web hiện đại, an toàn để xử lý tệp của bạn trực tiếp trong trình duyệt. Điều này có nghĩa là hiệu suất nhanh hơn, quyền riêng tư mạnh mẽ hơn và hoàn toàn yên tâm." + }, + "browserBased": { + "question": "Xử lý dựa trên trình duyệt giữ tôi an toàn như thế nào?", + "answer": "Bằng cách chạy hoàn toàn bên trong trình duyệt của bạn, BentoPDF đảm bảo rằng tệp của bạn không bao giờ rời khỏi thiết bị. Điều này loại bỏ các rủi ro về hack máy chủ, vi phạm dữ liệu hoặc truy cập trái phép. Tệp của bạn vẫn thuộc về bạn—luôn luôn." + }, + "analytics": { + "question": "Bạn có sử dụng cookie hoặc phân tích để theo dõi tôi không?", + "answer": "Chúng tôi quan tâm đến quyền riêng tư của bạn. BentoPDF không theo dõi thông tin cá nhân. Chúng tôi chỉ sử dụng Simple Analytics để xem số lượt truy cập ẩn danh. Điều này có nghĩa là chúng tôi có thể biết có bao nhiêu người dùng truy cập trang web của chúng tôi, nhưng chúng tôi không bao giờ biết bạn là ai. Simple Analytics hoàn toàn tuân thủ GDPR và tôn trọng quyền riêng tư của bạn." + } + }, + "testimonials": { + "title": "Người dùng", + "users": "của chúng tôi", + "say": "nói gì" + }, + "support": { + "title": "Thích công việc của tôi?", + "description": "BentoPDF là một dự án đam mê, được xây dựng để cung cấp bộ công cụ PDF miễn phí, riêng tư và mạnh mẽ cho mọi người. Nếu bạn thấy nó hữu ích, hãy cân nhắc hỗ trợ phát triển của nó. Mỗi ly cà phê đều giúp ích!", + "buyMeCoffee": "Mua cho tôi một ly cà phê" + }, + "footer": { + "copyright": "© 2026 BentoPDF. Bảo lưu mọi quyền.", + "version": "Phiên bản", + "company": "Công ty", + "aboutUs": "Về chúng tôi", + "faqLink": "FAQ", + "contactUs": "Liên hệ", + "legal": "Pháp lý", + "termsAndConditions": "Điều khoản và Điều kiện", + "privacyPolicy": "Chính sách Bảo mật", + "followUs": "Theo dõi chúng tôi" + }, + "merge": { + "title": "Gộp PDF", + "description": "Kết hợp toàn bộ tệp hoặc chọn các trang cụ thể để gộp thành tài liệu mới.", + "fileMode": "Chế độ tệp", + "pageMode": "Chế độ trang", + "howItWorks": "Cách hoạt động:", + "fileModeInstructions": [ + "Nhấp và kéo biểu tượng để thay đổi thứ tự các tệp.", + "Trong hộp \"Trang\" cho mỗi tệp, bạn có thể chỉ định phạm vi (ví dụ: \"1-3, 5\") để chỉ gộp những trang đó.", + "Để trống hộp \"Trang\" để bao gồm tất cả các trang từ tệp đó." + ], + "pageModeInstructions": [ + "Tất cả các trang từ PDF đã tải lên của bạn được hiển thị bên dưới.", + "Chỉ cần kéo và thả các hình thu nhỏ trang riêng lẻ để tạo thứ tự chính xác bạn muốn cho tệp mới của mình." + ], + "mergePdfs": "Gộp PDF" + }, + "common": { + "page": "Trang", + "pages": "Trang", + "of": "của", + "download": "Tải xuống", + "cancel": "Hủy", + "save": "Lưu", + "delete": "Xóa", + "edit": "Chỉnh sửa", + "add": "Thêm", + "remove": "Xóa", + "loading": "Đang tải...", + "error": "Lỗi", + "success": "Thành công", + "file": "Tệp", + "files": "Tệp" + }, + "about": { + "hero": { + "title": "Chúng tôi tin rằng công cụ PDF nên", + "subtitle": "nhanh, riêng tư và miễn phí.", + "noCompromises": "Không thỏa hiệp." + }, + "mission": { + "title": "Sứ mệnh của chúng tôi", + "description": "Cung cấp bộ công cụ PDF toàn diện nhất tôn trọng quyền riêng tư của bạn và không bao giờ yêu cầu thanh toán. Chúng tôi tin rằng các công cụ tài liệu thiết yếu nên có thể truy cập được cho mọi người, ở mọi nơi, không có rào cản." + }, + "philosophy": { + "label": "Triết lý cốt lõi của chúng tôi", + "title": "Quyền riêng tư trước tiên. Luôn luôn.", + "description": "Trong thời đại mà dữ liệu là hàng hóa, chúng tôi có cách tiếp cận khác. Tất cả quá trình xử lý cho các công cụ Bentopdf diễn ra cục bộ trong trình duyệt của bạn. Điều này có nghĩa là tệp của bạn không bao giờ chạm vào máy chủ của chúng tôi, chúng tôi không bao giờ thấy tài liệu của bạn và chúng tôi không theo dõi những gì bạn làm. Tài liệu của bạn vẫn hoàn toàn và rõ ràng là riêng tư. Đó không chỉ là một tính năng; đó là nền tảng của chúng tôi." + }, + "whyBentopdf": { + "title": "Tại sao chọn", + "speed": { + "title": "Được xây dựng cho tốc độ", + "description": "Không cần chờ tải lên hoặc tải xuống lên máy chủ. Bằng cách xử lý tệp trực tiếp trong trình duyệt của bạn bằng công nghệ web hiện đại như WebAssembly, chúng tôi cung cấp tốc độ vô song cho tất cả các công cụ của chúng tôi." + }, + "free": { + "title": "Hoàn toàn miễn phí", + "description": "Không dùng thử, không đăng ký, không phí ẩn và không có tính năng \"premium\" bị giữ lại. Chúng tôi tin rằng các công cụ PDF mạnh mẽ nên là tiện ích công cộng, không phải trung tâm lợi nhuận." + }, + "noAccount": { + "title": "Không cần tài khoản", + "description": "Bắt đầu sử dụng bất kỳ công cụ nào ngay lập tức. Chúng tôi không cần email, mật khẩu hoặc bất kỳ thông tin cá nhân nào của bạn. Quy trình làm việc của bạn nên không ma sát và ẩn danh." + }, + "openSource": { + "title": "Tinh thần mã nguồn mở", + "description": "Được xây dựng với tinh thần minh bạch. Chúng tôi tận dụng các thư viện mã nguồn mở tuyệt vời như PDF-lib và PDF.js, và tin vào nỗ lực do cộng đồng thúc đẩy để làm cho các công cụ mạnh mẽ có thể truy cập được cho mọi người." + } + }, + "cta": { + "title": "Sẵn sàng bắt đầu?", + "description": "Tham gia cùng hàng nghìn người dùng tin tưởng Bentopdf cho nhu cầu tài liệu hàng ngày của họ. Trải nghiệm sự khác biệt mà quyền riêng tư và hiệu suất có thể tạo ra.", + "button": "Khám phá tất cả công cụ" + } + }, + "contact": { + "title": "Liên hệ", + "subtitle": "Chúng tôi rất muốn nghe từ bạn. Cho dù bạn có câu hỏi, phản hồi hay yêu cầu tính năng, vui lòng đừng ngần ngại liên hệ.", + "email": "Bạn có thể liên hệ trực tiếp với chúng tôi qua email tại:" + }, + "licensing": { + "title": "Giấy phép cho", + "subtitle": "Chọn giấy phép phù hợp với nhu cầu của bạn." + }, + "multiTool": { + "uploadPdfs": "Tải lên PDF", + "upload": "Tải lên", + "addBlankPage": "Thêm trang trống", + "edit": "Chỉnh sửa:", + "undo": "Hoàn tác", + "redo": "Làm lại", + "reset": "Đặt lại", + "selection": "Chọn:", + "selectAll": "Chọn tất cả", + "deselectAll": "Bỏ chọn tất cả", + "rotate": "Xoay:", + "rotateLeft": "Trái", + "rotateRight": "Phải", + "transform": "Biến đổi:", + "duplicate": "Nhân bản", + "split": "Chia", + "clear": "Xóa:", + "delete": "Xóa", + "download": "Tải xuống:", + "downloadSelected": "Tải xuống đã chọn", + "exportPdf": "Xuất PDF", + "uploadPdfFiles": "Chọn tệp PDF", + "dragAndDrop": "Kéo và thả tệp PDF vào đây, hoặc nhấp để chọn", + "selectFiles": "Chọn tệp", + "renderingPages": "Đang kết xuất trang...", + "actions": { + "duplicatePage": "Nhân bản trang này", + "deletePage": "Xóa trang này", + "insertPdf": "Chèn PDF sau trang này", + "toggleSplit": "Bật/tắt chia sau trang này" + }, + "pleaseWait": "Vui lòng đợi", + "pagesRendering": "Các trang vẫn đang được kết xuất. Vui lòng đợi...", + "noPagesSelected": "Chưa chọn trang nào", + "selectOnePage": "Vui lòng chọn ít nhất một trang để tải xuống.", + "noPages": "Không có trang", + "noPagesToExport": "Không có trang nào để xuất.", + "renderingTitle": "Đang kết xuất xem trước trang", + "errorRendering": "Không thể kết xuất hình thu nhỏ trang", + "error": "Lỗi", + "failedToLoad": "Không thể tải" + } +} diff --git a/public/locales/vi/tools.json b/public/locales/vi/tools.json index 894c316..04b37af 100644 --- a/public/locales/vi/tools.json +++ b/public/locales/vi/tools.json @@ -1,282 +1,533 @@ { - "categories": { - "popularTools": "Công cụ phổ biến", - "editAnnotate": "Chỉnh sửa & Ghi chú", - "convertToPdf": "Chuyển đổi sang PDF", - "convertFromPdf": "Chuyển đổi từ PDF", - "organizeManage": "Sắp xếp & Quản lý", - "optimizeRepair": "Tối ưu hóa & Sửa chữa", - "securePdf": "Bảo mật PDF" - }, - "pdfMultiTool": { - "name": "Công cụ đa năng PDF", - "subtitle": "Gộp, Chia, Sắp xếp, Xóa, Xoay, Thêm trang trống, Trích xuất và Nhân đôi trong một giao diện thống nhất." - }, - "mergePdf": { - "name": "Gộp PDF", - "subtitle": "Kết hợp nhiều PDF thành một tệp. Giữ nguyên Bookmark." - }, - "splitPdf": { - "name": "Chia PDF", - "subtitle": "Trích xuất một phạm vi trang thành PDF mới." - }, - "compressPdf": { - "name": "Nén PDF", - "subtitle": "Giảm kích thước tệp PDF của bạn." - }, - "pdfEditor": { - "name": "Trình chỉnh sửa PDF", - "subtitle": "Ghi chú, tô sáng, chỉnh sửa, bình luận, thêm hình dạng/hình ảnh, tìm kiếm và xem PDF." - }, - "jpgToPdf": { - "name": "JPG sang PDF", - "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh JPG." - }, - "signPdf": { - "name": "Ký PDF", - "subtitle": "Vẽ, gõ hoặc tải lên chữ ký của bạn." - }, - "cropPdf": { - "name": "Cắt PDF", - "subtitle": "Cắt lề của mọi trang trong PDF của bạn." - }, - "extractPages": { - "name": "Trích xuất trang", - "subtitle": "Lưu một lựa chọn trang dưới dạng tệp mới." - }, - "duplicateOrganize": { - "name": "Nhân đôi & Sắp xếp", - "subtitle": "Nhân đôi, sắp xếp lại và xóa trang." - }, - "deletePages": { - "name": "Xóa trang", - "subtitle": "Xóa các trang cụ thể khỏi tài liệu của bạn." - }, - "editBookmarks": { - "name": "Chỉnh sửa Bookmark", - "subtitle": "Thêm, chỉnh sửa, nhập, xóa và trích xuất bookmark PDF." - }, - "tableOfContents": { - "name": "Mục lục", - "subtitle": "Tạo trang mục lục từ bookmark PDF." - }, - "pageNumbers": { - "name": "Số trang", - "subtitle": "Chèn số trang vào tài liệu của bạn." - }, - "addWatermark": { - "name": "Thêm Watermark", - "subtitle": "Đóng dấu văn bản hoặc hình ảnh lên các trang PDF của bạn." - }, - "headerFooter": { - "name": "Đầu trang & Chân trang", - "subtitle": "Thêm văn bản vào đầu và cuối trang." - }, - "invertColors": { - "name": "Đảo ngược màu", - "subtitle": "Tạo phiên bản \"chế độ tối\" cho PDF của bạn." - }, - "backgroundColor": { - "name": "Màu nền", - "subtitle": "Thay đổi màu nền của PDF của bạn." - }, - "changeTextColor": { - "name": "Thay đổi màu văn bản", - "subtitle": "Thay đổi màu văn bản trong PDF của bạn." - }, - "addStamps": { - "name": "Thêm tem", - "subtitle": "Thêm tem hình ảnh vào PDF của bạn bằng thanh công cụ ghi chú.", - "usernameLabel": "Tên người dùng tem", - "usernamePlaceholder": "Nhập tên của bạn (cho tem)", - "usernameHint": "Tên này sẽ xuất hiện trên các tem bạn tạo." - }, - "removeAnnotations": { - "name": "Xóa ghi chú", - "subtitle": "Loại bỏ bình luận, tô sáng và liên kết." - }, - "pdfFormFiller": { - "name": "Điền form PDF", - "subtitle": "Điền form trực tiếp trong trình duyệt. Cũng hỗ trợ form XFA." - }, - "createPdfForm": { - "name": "Tạo form PDF", - "subtitle": "Tạo form PDF có thể điền với các trường văn bản kéo và thả." - }, - "removeBlankPages": { - "name": "Xóa trang trống", - "subtitle": "Tự động phát hiện và xóa trang trống." - }, - "imageToPdf": { - "name": "Hình ảnh sang PDF", - "subtitle": "Chuyển đổi JPG, PNG, WebP, BMP, TIFF, SVG, HEIC sang PDF." - }, - "pngToPdf": { - "name": "PNG sang PDF", - "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh PNG." - }, - "webpToPdf": { - "name": "WebP sang PDF", - "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh WebP." - }, - "svgToPdf": { - "name": "SVG sang PDF", - "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh SVG." - }, - "bmpToPdf": { - "name": "BMP sang PDF", - "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh BMP." - }, - "heicToPdf": { - "name": "HEIC sang PDF", - "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh HEIC." - }, - "tiffToPdf": { - "name": "TIFF sang PDF", - "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh TIFF." - }, - "textToPdf": { - "name": "Văn bản sang PDF", - "subtitle": "Chuyển đổi tệp văn bản thuần túy thành PDF." - }, - "jsonToPdf": { - "name": "JSON sang PDF", - "subtitle": "Chuyển đổi tệp JSON sang định dạng PDF." - }, - "pdfToJpg": { - "name": "PDF sang JPG", - "subtitle": "Chuyển đổi mỗi trang PDF thành hình ảnh JPG." - }, - "pdfToPng": { - "name": "PDF sang PNG", - "subtitle": "Chuyển đổi mỗi trang PDF thành hình ảnh PNG." - }, - "pdfToWebp": { - "name": "PDF sang WebP", - "subtitle": "Chuyển đổi mỗi trang PDF thành hình ảnh WebP." - }, - "pdfToBmp": { - "name": "PDF sang BMP", - "subtitle": "Chuyển đổi mỗi trang PDF thành hình ảnh BMP." - }, - "pdfToTiff": { - "name": "PDF sang TIFF", - "subtitle": "Chuyển đổi mỗi trang PDF thành hình ảnh TIFF." - }, - "pdfToGreyscale": { - "name": "PDF sang thang xám", - "subtitle": "Chuyển đổi tất cả màu sắc sang đen trắng." - }, - "pdfToJson": { - "name": "PDF sang JSON", - "subtitle": "Chuyển đổi tệp PDF sang định dạng JSON." - }, - "ocrPdf": { - "name": "OCR PDF", - "subtitle": "Làm cho PDF có thể tìm kiếm và sao chép được." - }, - "alternateMix": { - "name": "Xen kẽ & Trộn trang", - "subtitle": "Gộp PDF bằng cách xen kẽ trang từ mỗi PDF. Giữ nguyên Bookmark." - }, - "addAttachments": { - "name": "Thêm tệp đính kèm", - "subtitle": "Nhúng một hoặc nhiều tệp vào PDF của bạn." - }, - "extractAttachments": { - "name": "Trích xuất tệp đính kèm", - "subtitle": "Trích xuất tất cả tệp được nhúng từ PDF thành ZIP." - }, - "editAttachments": { - "name": "Chỉnh sửa tệp đính kèm", - "subtitle": "Xem hoặc xóa tệp đính kèm trong PDF của bạn." - }, - "dividePages": { - "name": "Chia trang", - "subtitle": "Chia trang theo chiều ngang hoặc chiều dọc." - }, - "addBlankPage": { - "name": "Thêm trang trống", - "subtitle": "Chèn trang trống ở bất kỳ đâu trong PDF của bạn." - }, - "reversePages": { - "name": "Đảo ngược trang", - "subtitle": "Lật ngược thứ tự tất cả các trang trong tài liệu của bạn." - }, - "rotatePdf": { - "name": "Xoay PDF", - "subtitle": "Xoay trang theo bội số 90 độ." - }, - "nUpPdf": { - "name": "N-Up PDF", - "subtitle": "Sắp xếp nhiều trang lên một tờ." - }, - "combineToSinglePage": { - "name": "Kết hợp thành một trang", - "subtitle": "Ghép tất cả các trang thành một cuộn liên tục." - }, - "viewMetadata": { - "name": "Xem Metadata", - "subtitle": "Kiểm tra các thuộc tính ẩn của PDF của bạn." - }, - "editMetadata": { - "name": "Chỉnh sửa Metadata", - "subtitle": "Thay đổi tác giả, tiêu đề và các thuộc tính khác." - }, - "pdfsToZip": { - "name": "PDF sang ZIP", - "subtitle": "Đóng gói nhiều tệp PDF thành kho lưu trữ ZIP." - }, - "comparePdfs": { - "name": "So sánh PDF", - "subtitle": "So sánh hai PDF cạnh nhau." - }, - "posterizePdf": { - "name": "Posterize PDF", - "subtitle": "Chia một trang lớn thành nhiều trang nhỏ hơn." - }, - "fixPageSize": { - "name": "Sửa kích thước trang", - "subtitle": "Chuẩn hóa tất cả các trang về cùng một kích thước." - }, - "linearizePdf": { - "name": "Tuyến tính hóa PDF", - "subtitle": "Tối ưu hóa PDF để xem web nhanh." - }, - "pageDimensions": { - "name": "Kích thước trang", - "subtitle": "Phân tích kích thước trang, hướng và đơn vị." - }, - "removeRestrictions": { - "name": "Xóa hạn chế", - "subtitle": "Xóa bảo vệ mật khẩu và hạn chế bảo mật liên quan đến tệp PDF được ký số." - }, - "repairPdf": { - "name": "Sửa chữa PDF", - "subtitle": "Khôi phục dữ liệu từ tệp PDF bị hỏng hoặc hư hỏng." - }, - "encryptPdf": { - "name": "Mã hóa PDF", - "subtitle": "Khóa PDF của bạn bằng cách thêm mật khẩu." - }, - "sanitizePdf": { - "name": "Làm sạch PDF", - "subtitle": "Xóa metadata, ghi chú, script và nhiều hơn nữa." - }, - "decryptPdf": { - "name": "Giải mã PDF", - "subtitle": "Mở khóa PDF bằng cách xóa bảo vệ mật khẩu." - }, - "flattenPdf": { - "name": "Làm phẳng PDF", - "subtitle": "Làm cho trường form và ghi chú không thể chỉnh sửa." - }, - "removeMetadata": { - "name": "Xóa Metadata", - "subtitle": "Loại bỏ dữ liệu ẩn khỏi PDF của bạn." - }, - "changePermissions": { - "name": "Thay đổi quyền", - "subtitle": "Đặt hoặc thay đổi quyền người dùng trên PDF." - } -} \ No newline at end of file + "categories": { + "popularTools": "Công cụ phổ biến", + "editAnnotate": "Chỉnh sửa & Ghi chú", + "convertToPdf": "Chuyển đổi sang PDF", + "convertFromPdf": "Chuyển đổi từ PDF", + "organizeManage": "Sắp xếp & Quản lý", + "optimizeRepair": "Tối ưu hóa & Sửa chữa", + "securePdf": "Bảo mật PDF" + }, + "pdfMultiTool": { + "name": "Công cụ đa năng PDF", + "subtitle": "Gộp, Chia, Sắp xếp, Xóa, Xoay, Thêm trang trống, Trích xuất và Nhân đôi trong một giao diện thống nhất." + }, + "mergePdf": { + "name": "Gộp PDF", + "subtitle": "Kết hợp nhiều PDF thành một tệp. Giữ nguyên Bookmark." + }, + "splitPdf": { + "name": "Chia PDF", + "subtitle": "Trích xuất một phạm vi trang thành PDF mới." + }, + "compressPdf": { + "name": "Nén PDF", + "subtitle": "Giảm kích thước tệp PDF của bạn.", + "algorithmLabel": "Thuật toán nén", + "condense": "Condense (Khuyến nghị)", + "photon": "Photon (Dành cho PDF nhiều ảnh)", + "condenseInfo": "Condense sử dụng nén nâng cao: loại bỏ dữ liệu thừa, tối ưu hóa hình ảnh, gọn phông chữ. Phù hợp với hầu hết PDF.", + "photonInfo": "Photon chuyển đổi trang thành hình ảnh. Dùng cho PDF nhiều ảnh/quét.", + "photonWarning": "Cảnh báo: Văn bản sẽ không thể chọn được và liên kết sẽ không hoạt động.", + "levelLabel": "Mức độ nén", + "light": "Nhẹ (Giữ chất lượng)", + "balanced": "Cân bằng (Khuyến nghị)", + "aggressive": "Mạnh (Tệp nhỏ hơn)", + "extreme": "Cực đoan (Nén tối đa)", + "grayscale": "Chuyển sang thang xám", + "grayscaleHint": "Giảm kích thước tệp bằng cách loại bỏ thông tin màu", + "customSettings": "Cài đặt tùy chỉnh", + "customSettingsHint": "Tinh chỉnh các thông số nén:", + "outputQuality": "Chất lượng đầu ra", + "resizeImagesTo": "Thay đổi kích thước ảnh thành", + "onlyProcessAbove": "Chỉ xử lý khi trên", + "removeMetadata": "Xóa siêu dữ liệu", + "subsetFonts": "Gọn phông chữ (xóa ký tự không dùng)", + "removeThumbnails": "Xóa hình thu nhỏ nhúng", + "compressButton": "Nén PDF" + }, + "pdfEditor": { + "name": "Trình chỉnh sửa PDF", + "subtitle": "Ghi chú, tô sáng, chỉnh sửa, bình luận, thêm hình dạng/hình ảnh, tìm kiếm và xem PDF." + }, + "jpgToPdf": { + "name": "JPG sang PDF", + "subtitle": "Tạo PDF từ hình ảnh JPG, JPEG và JPEG2000 (JP2/JPX)." + }, + "signPdf": { + "name": "Ký PDF", + "subtitle": "Vẽ, gõ hoặc tải lên chữ ký của bạn." + }, + "cropPdf": { + "name": "Cắt PDF", + "subtitle": "Cắt lề của mọi trang trong PDF của bạn." + }, + "extractPages": { + "name": "Trích xuất trang", + "subtitle": "Lưu một lựa chọn trang dưới dạng tệp mới." + }, + "duplicateOrganize": { + "name": "Nhân đôi & Sắp xếp", + "subtitle": "Nhân đôi, sắp xếp lại và xóa trang." + }, + "deletePages": { + "name": "Xóa trang", + "subtitle": "Xóa các trang cụ thể khỏi tài liệu của bạn." + }, + "editBookmarks": { + "name": "Chỉnh sửa Bookmark", + "subtitle": "Thêm, chỉnh sửa, nhập, xóa và trích xuất bookmark PDF." + }, + "tableOfContents": { + "name": "Mục lục", + "subtitle": "Tạo trang mục lục từ bookmark PDF." + }, + "pageNumbers": { + "name": "Số trang", + "subtitle": "Chèn số trang vào tài liệu của bạn." + }, + "addWatermark": { + "name": "Thêm Watermark", + "subtitle": "Đóng dấu văn bản hoặc hình ảnh lên các trang PDF của bạn." + }, + "headerFooter": { + "name": "Đầu trang & Chân trang", + "subtitle": "Thêm văn bản vào đầu và cuối trang." + }, + "invertColors": { + "name": "Đảo ngược màu", + "subtitle": "Tạo phiên bản \"chế độ tối\" cho PDF của bạn." + }, + "backgroundColor": { + "name": "Màu nền", + "subtitle": "Thay đổi màu nền của PDF của bạn." + }, + "changeTextColor": { + "name": "Thay đổi màu văn bản", + "subtitle": "Thay đổi màu văn bản trong PDF của bạn." + }, + "addStamps": { + "name": "Thêm tem", + "subtitle": "Thêm tem hình ảnh vào PDF của bạn bằng thanh công cụ ghi chú.", + "usernameLabel": "Tên người dùng tem", + "usernamePlaceholder": "Nhập tên của bạn (cho tem)", + "usernameHint": "Tên này sẽ xuất hiện trên các tem bạn tạo." + }, + "removeAnnotations": { + "name": "Xóa ghi chú", + "subtitle": "Loại bỏ bình luận, tô sáng và liên kết." + }, + "pdfFormFiller": { + "name": "Điền form PDF", + "subtitle": "Điền form trực tiếp trong trình duyệt. Cũng hỗ trợ form XFA." + }, + "createPdfForm": { + "name": "Tạo form PDF", + "subtitle": "Tạo form PDF có thể điền với các trường văn bản kéo và thả." + }, + "removeBlankPages": { + "name": "Xóa trang trống", + "subtitle": "Tự động phát hiện và xóa trang trống." + }, + "imageToPdf": { + "name": "Hình ảnh sang PDF", + "subtitle": "Chuyển đổi JPG, PNG, BMP, GIF, TIFF, PNM, PGM, PBM, PPM, PAM, JXR, JPX, JP2, PSD, SVG, HEIC, WebP sang PDF." + }, + "pngToPdf": { + "name": "PNG sang PDF", + "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh PNG." + }, + "webpToPdf": { + "name": "WebP sang PDF", + "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh WebP." + }, + "svgToPdf": { + "name": "SVG sang PDF", + "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh SVG." + }, + "bmpToPdf": { + "name": "BMP sang PDF", + "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh BMP." + }, + "heicToPdf": { + "name": "HEIC sang PDF", + "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh HEIC." + }, + "tiffToPdf": { + "name": "TIFF sang PDF", + "subtitle": "Tạo PDF từ một hoặc nhiều hình ảnh TIFF." + }, + "textToPdf": { + "name": "Văn bản sang PDF", + "subtitle": "Chuyển đổi tệp văn bản thuần túy thành PDF." + }, + "jsonToPdf": { + "name": "JSON sang PDF", + "subtitle": "Chuyển đổi tệp JSON sang định dạng PDF." + }, + "pdfToJpg": { + "name": "PDF sang JPG", + "subtitle": "Chuyển đổi mỗi trang PDF thành hình ảnh JPG." + }, + "pdfToPng": { + "name": "PDF sang PNG", + "subtitle": "Chuyển đổi mỗi trang PDF thành hình ảnh PNG." + }, + "pdfToWebp": { + "name": "PDF sang WebP", + "subtitle": "Chuyển đổi mỗi trang PDF thành hình ảnh WebP." + }, + "pdfToBmp": { + "name": "PDF sang BMP", + "subtitle": "Chuyển đổi mỗi trang PDF thành hình ảnh BMP." + }, + "pdfToTiff": { + "name": "PDF sang TIFF", + "subtitle": "Chuyển đổi mỗi trang PDF thành hình ảnh TIFF." + }, + "pdfToGreyscale": { + "name": "PDF sang thang xám", + "subtitle": "Chuyển đổi tất cả màu sắc sang đen trắng." + }, + "pdfToJson": { + "name": "PDF sang JSON", + "subtitle": "Chuyển đổi tệp PDF sang định dạng JSON." + }, + "ocrPdf": { + "name": "OCR PDF", + "subtitle": "Làm cho PDF có thể tìm kiếm và sao chép được." + }, + "alternateMix": { + "name": "Xen kẽ & Trộn trang", + "subtitle": "Gộp PDF bằng cách xen kẽ trang từ mỗi PDF. Giữ nguyên Bookmark." + }, + "addAttachments": { + "name": "Thêm tệp đính kèm", + "subtitle": "Nhúng một hoặc nhiều tệp vào PDF của bạn." + }, + "extractAttachments": { + "name": "Trích xuất tệp đính kèm", + "subtitle": "Trích xuất tất cả tệp được nhúng từ PDF thành ZIP." + }, + "editAttachments": { + "name": "Chỉnh sửa tệp đính kèm", + "subtitle": "Xem hoặc xóa tệp đính kèm trong PDF của bạn." + }, + "dividePages": { + "name": "Chia trang", + "subtitle": "Chia trang theo chiều ngang hoặc chiều dọc." + }, + "addBlankPage": { + "name": "Thêm trang trống", + "subtitle": "Chèn trang trống ở bất kỳ đâu trong PDF của bạn." + }, + "reversePages": { + "name": "Đảo ngược trang", + "subtitle": "Lật ngược thứ tự tất cả các trang trong tài liệu của bạn." + }, + "rotatePdf": { + "name": "Xoay PDF", + "subtitle": "Xoay trang theo bội số 90 độ." + }, + "rotateCustom": { + "name": "Xoay theo độ tùy chỉnh", + "subtitle": "Xoay trang theo bất kỳ góc độ tùy chỉnh nào." + }, + "nUpPdf": { + "name": "N-Up PDF", + "subtitle": "Sắp xếp nhiều trang lên một tờ." + }, + "combineToSinglePage": { + "name": "Kết hợp thành một trang", + "subtitle": "Ghép tất cả các trang thành một cuộn liên tục." + }, + "viewMetadata": { + "name": "Xem Metadata", + "subtitle": "Kiểm tra các thuộc tính ẩn của PDF của bạn." + }, + "editMetadata": { + "name": "Chỉnh sửa Metadata", + "subtitle": "Thay đổi tác giả, tiêu đề và các thuộc tính khác." + }, + "pdfsToZip": { + "name": "PDF sang ZIP", + "subtitle": "Đóng gói nhiều tệp PDF thành kho lưu trữ ZIP." + }, + "comparePdfs": { + "name": "So sánh PDF", + "subtitle": "So sánh hai PDF cạnh nhau." + }, + "posterizePdf": { + "name": "Posterize PDF", + "subtitle": "Chia một trang lớn thành nhiều trang nhỏ hơn." + }, + "fixPageSize": { + "name": "Sửa kích thước trang", + "subtitle": "Chuẩn hóa tất cả các trang về cùng một kích thước." + }, + "linearizePdf": { + "name": "Tuyến tính hóa PDF", + "subtitle": "Tối ưu hóa PDF để xem web nhanh." + }, + "pageDimensions": { + "name": "Kích thước trang", + "subtitle": "Phân tích kích thước trang, hướng và đơn vị." + }, + "removeRestrictions": { + "name": "Xóa hạn chế", + "subtitle": "Xóa bảo vệ mật khẩu và hạn chế bảo mật liên quan đến tệp PDF được ký số." + }, + "repairPdf": { + "name": "Sửa chữa PDF", + "subtitle": "Khôi phục dữ liệu từ tệp PDF bị hỏng hoặc hư hỏng." + }, + "encryptPdf": { + "name": "Mã hóa PDF", + "subtitle": "Khóa PDF của bạn bằng cách thêm mật khẩu." + }, + "sanitizePdf": { + "name": "Làm sạch PDF", + "subtitle": "Xóa metadata, ghi chú, script và nhiều hơn nữa." + }, + "decryptPdf": { + "name": "Giải mã PDF", + "subtitle": "Mở khóa PDF bằng cách xóa bảo vệ mật khẩu." + }, + "flattenPdf": { + "name": "Làm phẳng PDF", + "subtitle": "Làm cho trường form và ghi chú không thể chỉnh sửa." + }, + "removeMetadata": { + "name": "Xóa Metadata", + "subtitle": "Loại bỏ dữ liệu ẩn khỏi PDF của bạn." + }, + "changePermissions": { + "name": "Thay đổi quyền", + "subtitle": "Đặt hoặc thay đổi quyền người dùng trên PDF." + }, + "odtToPdf": { + "name": "ODT sang PDF", + "subtitle": "Chuyển đổi tệp OpenDocument Text sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp ODT", + "convertButton": "Chuyển đổi sang PDF" + }, + "csvToPdf": { + "name": "CSV sang PDF", + "subtitle": "Chuyển đổi tệp bảng tính CSV sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp CSV", + "convertButton": "Chuyển đổi sang PDF" + }, + "rtfToPdf": { + "name": "RTF sang PDF", + "subtitle": "Chuyển đổi tài liệu Rich Text Format sang PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp RTF", + "convertButton": "Chuyển đổi sang PDF" + }, + "wordToPdf": { + "name": "Word sang PDF", + "subtitle": "Chuyển đổi tài liệu Word (DOCX, DOC, ODT, RTF) sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp DOCX, DOC, ODT, RTF", + "convertButton": "Chuyển đổi sang PDF" + }, + "excelToPdf": { + "name": "Excel sang PDF", + "subtitle": "Chuyển đổi bảng tính Excel (XLSX, XLS, ODS, CSV) sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp XLSX, XLS, ODS, CSV", + "convertButton": "Chuyển đổi sang PDF" + }, + "powerpointToPdf": { + "name": "PowerPoint sang PDF", + "subtitle": "Chuyển đổi bài thuyết trình PowerPoint (PPTX, PPT, ODP) sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp PPTX, PPT, ODP", + "convertButton": "Chuyển đổi sang PDF" + }, + "markdownToPdf": { + "name": "Markdown sang PDF", + "subtitle": "Viết hoặc dán Markdown và xuất nó thành PDF được định dạng đẹp.", + "paneMarkdown": "Markdown", + "panePreview": "Xem trước", + "btnUpload": "Tải lên", + "btnSyncScroll": "Cuộn đồng bộ", + "btnSettings": "Cài đặt", + "btnExportPdf": "Xuất PDF", + "settingsTitle": "Cài đặt Markdown", + "settingsPreset": "Cài đặt sẵn", + "presetDefault": "Mặc định (kiểu GFM)", + "presetCommonmark": "CommonMark (nghiêm ngặt)", + "presetZero": "Tối thiểu (không có tính năng)", + "settingsOptions": "Tùy chọn Markdown", + "optAllowHtml": "Cho phép thẻ HTML", + "optBreaks": "Chuyển đổi xuống dòng thành
", + "optLinkify": "Tự động chuyển URL thành liên kết", + "optTypographer": "Trình sắp chữ (dấu ngoặc thông minh, v.v.)" + }, + "pdfBooklet": { + "name": "Sách nhỏ PDF", + "subtitle": "Sắp xếp lại các trang để in sách nhỏ hai mặt. Gấp và đóng ghim để tạo sách nhỏ.", + "howItWorks": "Cách hoạt động:", + "step1": "Tải lên tệp PDF.", + "step2": "Các trang sẽ được sắp xếp lại theo thứ tự sách nhỏ.", + "step3": "In hai mặt, lật cạnh ngắn, gấp và đóng ghim.", + "paperSize": "Kích thước giấy", + "orientation": "Hướng", + "portrait": "Dọc", + "landscape": "Ngang", + "pagesPerSheet": "Số trang mỗi tờ", + "createBooklet": "Tạo sách nhỏ", + "processing": "Đang xử lý...", + "pageCount": "Số trang sẽ được bổ sung lên bội số của 4 nếu cần." + }, + "xpsToPdf": { + "name": "XPS sang PDF", + "subtitle": "Chuyển đổi tài liệu XPS/OXPS sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp XPS, OXPS", + "convertButton": "Chuyển đổi sang PDF" + }, + "mobiToPdf": { + "name": "MOBI sang PDF", + "subtitle": "Chuyển đổi sách điện tử MOBI sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp MOBI", + "convertButton": "Chuyển đổi sang PDF" + }, + "epubToPdf": { + "name": "EPUB sang PDF", + "subtitle": "Chuyển đổi sách điện tử EPUB sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp EPUB", + "convertButton": "Chuyển đổi sang PDF" + }, + "fb2ToPdf": { + "name": "FB2 sang PDF", + "subtitle": "Chuyển đổi sách điện tử FictionBook (FB2) sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp FB2", + "convertButton": "Chuyển đổi sang PDF" + }, + "cbzToPdf": { + "name": "CBZ sang PDF", + "subtitle": "Chuyển đổi kho lưu trữ truyện tranh (CBZ/CBR) sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp CBZ, CBR", + "convertButton": "Chuyển đổi sang PDF" + }, + "wpdToPdf": { + "name": "WPD sang PDF", + "subtitle": "Chuyển đổi tài liệu WordPerfect (WPD) sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp WPD", + "convertButton": "Chuyển đổi sang PDF" + }, + "wpsToPdf": { + "name": "WPS sang PDF", + "subtitle": "Chuyển đổi tài liệu WPS Office sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp WPS", + "convertButton": "Chuyển đổi sang PDF" + }, + "xmlToPdf": { + "name": "XML sang PDF", + "subtitle": "Chuyển đổi tài liệu XML sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp XML", + "convertButton": "Chuyển đổi sang PDF" + }, + "pagesToPdf": { + "name": "Pages sang PDF", + "subtitle": "Chuyển đổi tài liệu Apple Pages sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp Pages", + "convertButton": "Chuyển đổi sang PDF" + }, + "odgToPdf": { + "name": "ODG sang PDF", + "subtitle": "Chuyển đổi tệp OpenDocument Graphics (ODG) sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp ODG", + "convertButton": "Chuyển đổi sang PDF" + }, + "odsToPdf": { + "name": "ODS sang PDF", + "subtitle": "Chuyển đổi tệp OpenDocument Spreadsheet (ODS) sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp ODS", + "convertButton": "Chuyển đổi sang PDF" + }, + "odpToPdf": { + "name": "ODP sang PDF", + "subtitle": "Chuyển đổi tệp OpenDocument Presentation (ODP) sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp ODP", + "convertButton": "Chuyển đổi sang PDF" + }, + "pubToPdf": { + "name": "PUB sang PDF", + "subtitle": "Chuyển đổi tệp Microsoft Publisher (PUB) sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp PUB", + "convertButton": "Chuyển đổi sang PDF" + }, + "vsdToPdf": { + "name": "VSD sang PDF", + "subtitle": "Chuyển đổi tệp Microsoft Visio (VSD, VSDX) sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp VSD, VSDX", + "convertButton": "Chuyển đổi sang PDF" + }, + "psdToPdf": { + "name": "PSD sang PDF", + "subtitle": "Chuyển đổi tệp Adobe Photoshop (PSD) sang định dạng PDF. Hỗ trợ nhiều tệp.", + "acceptedFormats": "Tệp PSD", + "convertButton": "Chuyển đổi sang PDF" + }, + "pdfToSvg": { + "name": "PDF sang SVG", + "subtitle": "Chuyển đổi mỗi trang PDF thành đồ họa vector có thể mở rộng (SVG) với chất lượng hoàn hảo ở mọi kích thước." + }, + "extractTables": { + "name": "Trích xuất bảng PDF", + "subtitle": "Trích xuất bảng từ tệp PDF và xuất dưới dạng CSV, JSON hoặc Markdown." + }, + "pdfToCsv": { + "name": "PDF sang CSV", + "subtitle": "Trích xuất bảng từ PDF và chuyển đổi sang định dạng CSV." + }, + "pdfToExcel": { + "name": "PDF sang Excel", + "subtitle": "Trích xuất bảng từ PDF và chuyển đổi sang định dạng Excel (XLSX)." + }, + "pdfToText": { + "name": "PDF sang Văn bản", + "subtitle": "Trích xuất văn bản từ tệp PDF và lưu dưới dạng tệp văn bản (.txt). Hỗ trợ nhiều tệp.", + "note": "Công cụ này CHỈ hoạt động với các tệp PDF được tạo kỹ thuật số. Đối với tài liệu quét hoặc PDF dựa trên hình ảnh, hãy sử dụng công cụ OCR PDF của chúng tôi.", + "convertButton": "Trích xuất văn bản" + }, + "digitalSignPdf": { + "name": "Chữ ký số PDF", + "pageTitle": "Chữ ký số PDF - Thêm chữ ký mật mã | BentoPDF", + "subtitle": "Thêm chữ ký số mật mã vào PDF của bạn bằng chứng chỉ X.509. Hỗ trợ định dạng PKCS#12 (.pfx, .p12) và PEM. Khóa riêng của bạn không bao giờ rời khỏi trình duyệt.", + "certificateSection": "Chứng chỉ", + "uploadCert": "Tải lên chứng chỉ (.pfx, .p12)", + "certPassword": "Mật khẩu chứng chỉ", + "certPasswordPlaceholder": "Nhập mật khẩu chứng chỉ", + "certInfo": "Thông tin chứng chỉ", + "certSubject": "Chủ thể", + "certIssuer": "Nhà phát hành", + "certValidity": "Hiệu lực", + "signatureDetails": "Chi tiết chữ ký (Tùy chọn)", + "reason": "Lý do", + "reasonPlaceholder": "ví dụ: Tôi phê duyệt tài liệu này", + "location": "Địa điểm", + "locationPlaceholder": "ví dụ: Hà Nội, Việt Nam", + "contactInfo": "Thông tin liên hệ", + "contactPlaceholder": "ví dụ: email@example.com", + "applySignature": "Áp dụng chữ ký số", + "successMessage": "Ký PDF thành công! Chữ ký có thể được xác minh trong bất kỳ trình đọc PDF nào." + }, + "validateSignaturePdf": { + "name": "Xác minh chữ ký PDF", + "pageTitle": "Xác minh chữ ký PDF - Xác thực chữ ký số | BentoPDF", + "subtitle": "Xác minh chữ ký số trong tệp PDF của bạn. Kiểm tra hiệu lực chứng chỉ, xem thông tin người ký và xác nhận tính toàn vẹn tài liệu. Tất cả xử lý diễn ra trong trình duyệt của bạn." + }, + "emailToPdf": { + "name": "Email sang PDF", + "subtitle": "Chuyển đổi tệp email (EML, MSG) sang định dạng PDF. Hỗ trợ xuất Outlook và định dạng email tiêu chuẩn.", + "acceptedFormats": "Tệp EML, MSG", + "convertButton": "Chuyển đổi sang PDF" + }, + "fontToOutline": { + "name": "Phông chữ thành đường viền", + "subtitle": "Chuyển đổi tất cả phông chữ thành đường viền vector để hiển thị nhất quán trên mọi thiết bị." + }, + "deskewPdf": { + "name": "Chỉnh nghiêng PDF", + "subtitle": "Tự động làm thẳng các trang quét bị nghiêng bằng OpenCV." + } +} diff --git a/public/locales/zh-TW/common.json b/public/locales/zh-TW/common.json new file mode 100644 index 0000000..777dde8 --- /dev/null +++ b/public/locales/zh-TW/common.json @@ -0,0 +1,323 @@ +{ + "nav": { + "home": "首頁", + "about": "關於我們", + "contact": "聯絡我們", + "licensing": "產品授權", + "allTools": "所有工具", + "openMainMenu": "開啟主選單", + "language": "語言" + }, + "donation": { + "message": "喜歡 BentoPDF?幫助我們保持免費和開源!", + "button": "捐贈" + }, + "hero": { + "title": "專為隱私打造的", + "pdfToolkit": "PDF 工具箱", + "builtForPrivacy": " ", + "noSignups": "不須註冊", + "unlimitedUse": "無限使用", + "worksOffline": "離線可用", + "startUsing": "立刻開始使用" + }, + "usedBy": { + "title": "被下列公司及其員工採用" + }, + "features": { + "title": "為何你該選擇", + "bentoPdf": "BentoPDF?", + "noSignup": { + "title": "不須註冊", + "description": "立即可用,不須帳號或電子郵件。" + }, + "noUploads": { + "title": "不須上傳", + "description": "所有文件都在用戶端處理,永遠不會離開你的裝置。" + }, + "foreverFree": { + "title": "永遠免費", + "description": "所有工具免費使用,沒有試用期,也沒有付費牆。" + }, + "noLimits": { + "title": "沒有限制", + "description": "隨心所欲的使用,沒有任何隱藏限制。" + }, + "batchProcessing": { + "title": "批量處理", + "description": "一次處理無限量的 PDF 檔案。" + }, + "lightningFast": { + "title": "快如閃電", + "description": "瞬間處理 PDF,無須忍受任何等待或延遲。" + } + }, + "tools": { + "title": "開始使用", + "toolsLabel": "工具", + "subtitle": "點擊任意工具以開始上傳檔案", + "searchPlaceholder": "搜尋工具(例如「合併」或「分割」...)", + "backToTools": "返回工具列表", + "firstLoadNotice": "首次載入需要一點時間,因為我們正在下載轉換引擎。之後所有載入將即時完成。" + }, + "upload": { + "clickToSelect": "點擊以選擇檔案", + "orDragAndDrop": "或將檔案拖放到此處", + "pdfOrImages": "PDF 或圖片", + "filesNeverLeave": "你的檔案永遠不會離開你的裝置。", + "addMore": "添加更多檔案", + "clearAll": "清除全部" + }, + "loader": { + "processing": "正在處理..." + }, + "alert": { + "title": "提示", + "ok": "確認" + }, + "preview": { + "title": "文件預覽", + "downloadAsPdf": "下載為 PDF", + "close": "關閉" + }, + "settings": { + "title": "設定", + "shortcuts": "快捷鍵", + "preferences": "偏好設定", + "displayPreferences": "顯示設定", + "searchShortcuts": "搜尋快捷鍵...", + "shortcutsInfo": "按下並按住按鍵以設定快捷鍵。變更將自動儲存。", + "shortcutsWarning": "⚠️ 避免使用瀏覽器常用快捷鍵(Cmd/Ctrl+W、Cmd/Ctrl+T、Cmd/Ctrl+N 等),它們可能無法穩定運作。", + "import": "匯入", + "export": "匯出", + "resetToDefaults": "恢復預設值", + "fullWidthMode": "全寬模式", + "fullWidthDescription": "使用全螢幕寬度而非置中容器顯示所有工具", + "settingsAutoSaved": "設定會自動儲存", + "clickToSet": "點擊以設定", + "pressKeys": "按下按鍵...", + "warnings": { + "alreadyInUse": "快捷鍵已被占用", + "assignedTo": "已被指定為:", + "chooseDifferent": "請選擇一個不同的快捷鍵。", + "reserved": "保留快捷鍵警告", + "commonlyUsed": "常被用於:", + "unreliable": "這個快捷鍵可能與系統/瀏覽器行為衝突或無法穩定運作。", + "useAnyway": "仍要使用嗎?", + "resetTitle": "重設快捷鍵", + "resetMessage": "確定要將所有快捷鍵恢復為預設值嗎?

這個操作無法被撤回。", + "importSuccessTitle": "匯入成功", + "importSuccessMessage": "快捷鍵匯入成功!", + "importFailTitle": "匯入失敗", + "importFailMessage": "匯入快捷鍵失敗。無效的檔案格式。" + } + }, + "warning": { + "title": "警告", + "cancel": "取消", + "proceed": "繼續" + }, + "compliance": { + "title": "你的資料永遠不會離開你的裝置", + "weKeep": "我們確保", + "yourInfoSafe": "你的資訊安全", + "byFollowingStandards": "遵循全球安全標準。", + "processingLocal": "所有處理過程都在你的裝置上進行。", + "gdpr": { + "title": "符合 GDPR 規範", + "description": "保護歐盟境內個人的數據及隱私。" + }, + "ccpa": { + "title": "符合 CCPA 規範", + "description": "賦予加州居民對其個人資訊如何被蒐集、使用及分享的權利。" + }, + "hipaa": { + "title": "符合 HIPAA 規範", + "description": "制定處理美國健保系統中敏感健康資訊的規範。" + } + }, + "faq": { + "title": "常見", + "questions": "問題", + "isFree": { + "question": "BentoPDF 真的是免費的嗎?", + "answer": "沒錯,完全免費。BentoPDF 上的所有工具均為 100% 免費使用,並且沒有檔案限制、無須註冊且無浮水印。我們相信每個人都值得免費使用簡單且強大的 PDF 工具。" + }, + "areFilesSecure": { + "question": "我的檔案都是安全的嗎?它們都在哪裡被處理?", + "answer": "你的檔案都非常安全,因為它們從未離開你的電腦。所有處理過程都直接在你的網頁瀏覽器中進行(用戶端)。我們永遠不會將你的檔案上傳到伺服器,因此你對你的文件保有完全的隱私與控制權。" + }, + "platforms": { + "question": "我能在 Mac、Windows 和行動裝置上使用嗎?", + "answer": "可以!由於 BentoPDF 完全在你的瀏覽器中運作,它在任何有著現代網頁瀏覽器的系統中都能運行,包含 Windows、macOS、Linux、iOS 和 Android。" + }, + "gdprCompliant": { + "question": "BentoPDF 符合 GDPR 規範嗎?", + "answer": "是的。BentoPDF 完全符合 GDPR 規範。由於所有檔案處理都在你的瀏覽器本地發生且我們永不蒐集或傳輸你的檔案至任何伺服器,我們無法存取你的資料。這確保你的文件永遠都在你的控制之中。" + }, + "dataStorage": { + "question": "你會保存或追蹤我的檔案嗎?", + "answer": "不。我們永不儲存、追蹤或記錄你的檔案。你在 BentoPDF 上進行的任何操作都發生在你的瀏覽器記憶體中,並且會在你關閉頁面後立即消失。沒有上傳、沒有歷史紀錄且無伺服器參與。" + }, + "different": { + "question": "BentoPDF 跟其他的 PDF 工具有何不同之處?", + "answer": "大多數 PDF 工具都透過將你的檔案上傳至伺服器好進行處理。BentoPDF 永遠不會那麼做。我們使用安全且現代的網頁科技以在你的瀏覽器中直接處理檔案。這意味著更快的性能、更強的隱私與完全的安心。" + }, + "browserBased": { + "question": "瀏覽器端處理如何保障我的安全?", + "answer": "透過完全在你的瀏覽器內運作,BentoPDF 確保你的文件從未離開你的裝置。這消除了伺服器遭駭、資料外洩與未授權訪問的風險。你的檔案永遠都屬於你。" + }, + "analytics": { + "question": "你會使用 Cookies 或網站分析來追蹤我嗎?", + "answer": "我們在乎你的隱私。BentoPDF 並不追蹤個人資訊。我們僅使用 Simple Analytics 來查看匿名訪問次數。這代表我們能知道有多少使用者造訪過我們的網站,但我們永遠都不會知道你是誰。Simple Analytics 完全符合 GDPR 規範且尊重你的隱私。" + } + }, + "testimonials": { + "title": "看看我們的", + "users": "使用者", + "say": "怎麼說" + }, + "support": { + "title": "喜歡我的作品嗎?", + "description": "BentoPDF 是一個出於熱情開發的專案,旨在為每個人提供一個免費、注重隱私且強大的 PDF 工具組。如果有幫上你的忙,請考慮支持它的開發。每杯咖啡都意義重大!", + "buyMeCoffee": "買杯咖啡給我" + }, + "footer": { + "copyright": "© 2026 BentoPDF。版權所有。", + "version": "版本", + "company": "公司", + "aboutUs": "關於我們", + "faqLink": "常見問題", + "contactUs": "聯絡我們", + "legal": "法律", + "termsAndConditions": "服務條款", + "privacyPolicy": "隱私政策", + "followUs": "關注我們" + }, + "merge": { + "title": "合併 PDF", + "description": "合併整個檔案,或選擇特定頁面合併為新文件。", + "fileMode": "檔案模式", + "pageMode": "頁面模式", + "howItWorks": "使用說明:", + "fileModeInstructions": [ + "點擊並抓取圖標來改變檔案順序。", + "在每個文件的「頁碼」框中,你可以僅指定想要合併的頁面範圍(例如「1-3, 5」)。", + "將「頁碼」框留空以包含該檔案的所有頁面。" + ], + "pageModeInstructions": [ + "下列是你上傳的 PDF 中的所有頁面。", + "只要將個別頁面縮圖拖放到指定位置,即可為新檔案建立您想要的精確排序。" + ], + "mergePdfs": "合併 PDF" + }, + "common": { + "page": "頁", + "pages": "頁", + "of": " / ", + "download": "下載", + "cancel": "取消", + "save": "儲存", + "delete": "刪除", + "edit": "編輯", + "add": "添加", + "remove": "移除", + "loading": "載入中...", + "error": "錯誤", + "success": "成功", + "file": "檔案", + "files": "檔案" + }, + "about": { + "hero": { + "title": "我們相信 PDF 工具應該", + "subtitle": "快速、私密且免費。", + "noCompromises": "絕不妥協。" + }, + "mission": { + "title": "我們的任務", + "description": "在尊重你的隱私且從不要求收費的同時提供最全面的 PDF 工具箱。我們相信核心文件工具應讓任何人隨時隨地不受限的使用。" + }, + "philosophy": { + "label": "我們的核心理念", + "title": "永遠以隱私為重。", + "description": "在數據被商品化的時代,我們採取截然不同的做法。所有 BentoPDF 工具的處理流程皆在你的瀏覽器本地完成。這意味著你的檔案絕不觸及我們的伺服器,我們從未看見你的文件內容,更不會追蹤你的行為。你的文件將始終保持無可置疑的私密性。這不僅是功能,更是我們的立身之本。" + }, + "whyBentopdf": { + "title": "為何選擇", + "speed": { + "title": "生來迅捷", + "description": "無需等待與伺服器間的上傳和下載。透過在你的瀏覽器中使用 WebAssembly 等現代網路科技處理檔案,我們得以為所有工具提供無與倫比的速度。" + }, + "free": { + "title": "完全免費", + "description": "沒有試用期、訂閱、隱藏費用與所謂的「高級」功能。我們相信強大的 PDF 工具應該是一種公共設施,而非以營利為重。" + }, + "noAccount": { + "title": "無須帳號", + "description": "立即開始使用任何工具。我們不需要你的電子郵件、密碼或任何個人資訊。你的工作流程應當匿名且不受阻礙。" + }, + "openSource": { + "title": "開源精神", + "description": "將透明性視為核心打造。我們使用了如 PDF-lib 和 PDF.js 等優秀的開源庫,並且相信社群驅動力能讓強大的工具惠及每一個人。" + } + }, + "cta": { + "title": "準備好開始了嗎?", + "description": "加入成千上萬信任 BentoPDF 能勝任他們日常文件需求的使用者們。體驗隱私與性能所帶來的差距。", + "button": "探索所有工具" + } + }, + "contact": { + "title": "保持聯絡", + "subtitle": "我們很樂意收到你的訊息。無論你想提出的是問題、回饋或功能請求,都請隨時聯繫我們。", + "email": "你可以直接透過電子郵件聯繫我們:" + }, + "licensing": { + "title": "授權使用", + "subtitle": "選擇適合需求的產品授權。" + }, + "multiTool": { + "uploadPdfs": "上傳 PDF", + "upload": "上傳", + "addBlankPage": "添加空白頁面", + "edit": "編輯:", + "undo": "復原", + "redo": "取消復原", + "reset": "重設", + "selection": "選取:", + "selectAll": "選取全部", + "deselectAll": "取消選取全部", + "rotate": "旋轉:", + "rotateLeft": "左", + "rotateRight": "右", + "transform": "變換:", + "duplicate": "複製", + "split": "分割", + "clear": "清除:", + "delete": "刪除", + "download": "下載:", + "downloadSelected": "下載選取的項目", + "exportPdf": "匯出 PDF", + "uploadPdfFiles": "選擇 PDF 檔案", + "dragAndDrop": "拖放 PDF 檔案至此處,或是點擊以選取", + "selectFiles": "選擇檔案", + "renderingPages": "渲染頁面...", + "actions": { + "duplicatePage": "複製此頁", + "deletePage": "刪除此頁", + "insertPdf": "在此頁後插入 PDF", + "toggleSplit": "在此頁後切換分割" + }, + "pleaseWait": "請稍後", + "pagesRendering": "正在渲染頁面。請稍後...", + "noPagesSelected": "未選擇頁面", + "selectOnePage": "請至少選擇一頁以開始下載。", + "noPages": "無頁面", + "noPagesToExport": "無可匯出的頁面。", + "renderingTitle": "正在渲染頁面預覽", + "errorRendering": "無法渲染頁面縮圖", + "error": "錯誤", + "failedToLoad": "載入失敗" + } +} diff --git a/public/locales/zh-TW/tools.json b/public/locales/zh-TW/tools.json new file mode 100644 index 0000000..6ef2fe0 --- /dev/null +++ b/public/locales/zh-TW/tools.json @@ -0,0 +1,511 @@ +{ + "categories": { + "popularTools": "熱門工具", + "editAnnotate": "編輯與註解", + "convertToPdf": "轉換為 PDF", + "convertFromPdf": "從 PDF 轉換", + "organizeManage": "組織與管理", + "optimizeRepair": "優化與修復", + "securePdf": "安全 PDF" + }, + "pdfMultiTool": { + "name": "PDF 多功能工具", + "subtitle": "在統一的頁面中合併、分割、組織、刪除、旋轉、添加空白頁面、提取與複製。" + }, + "mergePdf": { + "name": "合併 PDF", + "subtitle": "將多個 PDF 合併為一個檔案。保留書籤。" + }, + "splitPdf": { + "name": "分割 PDF", + "subtitle": "將指定範圍的頁面提取為新的 PDF。" + }, + "compressPdf": { + "name": "壓縮 PDF", + "subtitle": "降低你的 PDF 檔案大小。" + }, + "pdfEditor": { + "name": "PDF 編輯器", + "subtitle": "註解、螢光、塗黑、評論、添加圖形或圖片、搜尋與查看 PDF。" + }, + "jpgToPdf": { + "name": "JPG 轉 PDF", + "subtitle": "從一張或多張 JPG 圖片建立 PDF。" + }, + "signPdf": { + "name": "簽署 PDF", + "subtitle": "繪製、輸入或上傳你的簽名。" + }, + "cropPdf": { + "name": "裁切 PDF", + "subtitle": "修剪你的 PDF 中所有頁面的邊界。" + }, + "extractPages": { + "name": "提取頁面", + "subtitle": "將選取的頁面保存為新的檔案。" + }, + "duplicateOrganize": { + "name": "複製與組織", + "subtitle": "複製、重新排序與刪除頁面。" + }, + "deletePages": { + "name": "刪除頁面", + "subtitle": "移除你的文件中的特定頁面。" + }, + "editBookmarks": { + "name": "編輯書籤", + "subtitle": "添加、編輯、匯入、刪除與提取 PDF 書籤。" + }, + "tableOfContents": { + "name": "目錄", + "subtitle": "從 PDF 書籤生成目錄頁。" + }, + "pageNumbers": { + "name": "頁碼", + "subtitle": "在你的文件中插入頁碼。" + }, + "addWatermark": { + "name": "添加浮水印", + "subtitle": "在你的 PDF 頁面上壓印文字或圖片。" + }, + "headerFooter": { + "name": "頁首與頁尾", + "subtitle": "在頁面的頂部與底部新增文字。" + }, + "invertColors": { + "name": "反轉顏色", + "subtitle": "為你的 PDF 建立深色版本。" + }, + "backgroundColor": { + "name": "背景顏色", + "subtitle": "更改你的 PDF 的背景顏色。" + }, + "changeTextColor": { + "name": "更改文字顏色", + "subtitle": "更改你的 PDF 中的文字顏色。" + }, + "addStamps": { + "name": "添加印章", + "subtitle": "使用註解工具列在你的 PDF 中添加圖片印章。", + "usernameLabel": "印章使用者名稱", + "usernamePlaceholder": "輸入你的名稱(印章用)", + "usernameHint": "該名稱會出現在你建立的印章上。" + }, + "removeAnnotations": { + "name": "移除註解", + "subtitle": "去除留言、螢光與連結。" + }, + "pdfFormFiller": { + "name": "PDF 表單填寫器", + "subtitle": "直接在你的瀏覽器中填寫表單。支援 XFA 表單。" + }, + "createPdfForm": { + "name": "建立 PDF 表單", + "subtitle": "透過拖放文字框建立可填寫的 PDF 表單。" + }, + "removeBlankPages": { + "name": "移除空白頁面", + "subtitle": "自動偵測並刪除空白頁面。" + }, + "imageToPdf": { + "name": "圖片轉 PDF", + "subtitle": "將 JPG、PNG、WebP、BMP、TIFF、SVG 與 HEIC 轉換為 PDF。" + }, + "pngToPdf": { + "name": "PNG 轉 PDF", + "subtitle": "從一張或多張 PNG 圖片建立 PDF。" + }, + "webpToPdf": { + "name": "WebP 轉 PDF", + "subtitle": "從一張或多張 WebP 圖片建立 PDF。" + }, + "svgToPdf": { + "name": "SVG 轉 PDF", + "subtitle": "從一張或多張 SVG 圖片建立 PDF。" + }, + "bmpToPdf": { + "name": "BMP 轉 PDF", + "subtitle": "從一張或多張 BMP 圖片建立 PDF。" + }, + "heicToPdf": { + "name": "HEIC 轉 PDF", + "subtitle": "從一張或多張 HEIC 圖片建立 PDF。" + }, + "tiffToPdf": { + "name": "TIFF 轉 PDF", + "subtitle": "從一張或多張 TIFF 圖片建立 PDF。" + }, + "textToPdf": { + "name": "Text 轉 PDF", + "subtitle": "將純文字檔案轉換為 PDF。" + }, + "jsonToPdf": { + "name": "JSON 轉 PDF", + "subtitle": "將 JSON 檔案轉換為 PDF 格式。" + }, + "pdfToJpg": { + "name": "PDF 轉 JPG", + "subtitle": "將每個 PDF 頁面轉換為 JPG 圖片。" + }, + "pdfToPng": { + "name": "PDF 轉 PNG", + "subtitle": "將每個 PDF 頁面轉換為 PNG 圖片。" + }, + "pdfToWebp": { + "name": "PDF 轉 WebP", + "subtitle": "將每個 PDF 頁面轉換為 WebP 圖片。" + }, + "pdfToBmp": { + "name": "PDF 轉 BMP", + "subtitle": "將每個 PDF 頁面轉換為 BMP 圖片。" + }, + "pdfToTiff": { + "name": "PDF 轉 TIFF", + "subtitle": "將每個 PDF 頁面轉換為 TIFF 圖片。" + }, + "pdfToGreyscale": { + "name": "PDF 轉灰階", + "subtitle": "將所有顏色轉換為黑白。" + }, + "pdfToJson": { + "name": "PDF 轉 JSON", + "subtitle": "將 PDF 檔案轉換為 JSON 格式。" + }, + "ocrPdf": { + "name": "OCR PDF", + "subtitle": "使 PDF 可搜尋且可複製。" + }, + "alternateMix": { + "name": "交錯混合頁面", + "subtitle": "將每個 PDF 的頁面交錯合併。保留書籤。" + }, + "addAttachments": { + "name": "添加附件", + "subtitle": "嵌入一個或多個檔案至你的 PDF 中。" + }, + "extractAttachments": { + "name": "提取附件", + "subtitle": "從 PDF 中提取所有嵌入的檔案為 ZIP。" + }, + "editAttachments": { + "name": "編輯附件", + "subtitle": "查看或移除你的 PDF 中的附件。" + }, + "dividePages": { + "name": "分割頁面", + "subtitle": "垂直或水平分割頁面。" + }, + "addBlankPage": { + "name": "添加空白頁面", + "subtitle": "在你的 PDF 中的任一位置插入空白頁面。" + }, + "reversePages": { + "name": "反轉頁面", + "subtitle": "反轉你的文件中所有頁面的順序。" + }, + "rotatePdf": { + "name": "旋轉 PDF", + "subtitle": "以 90 度增量旋轉頁面。" + }, + "nUpPdf": { + "name": "N-Up PDF", + "subtitle": "將多個頁面排列在單張紙上。" + }, + "combineToSinglePage": { + "name": "合併為單一頁面", + "subtitle": "將所有頁面縫合為一個單一且連續的滾動頁面。" + }, + "viewMetadata": { + "name": "查看元資料", + "subtitle": "檢視你的 PDF 中的隱藏屬性。" + }, + "editMetadata": { + "name": "編輯元資料", + "subtitle": "更改作者、標題和其他屬性。" + }, + "pdfsToZip": { + "name": "PDF 轉 ZIP", + "subtitle": "將多個 PDF 檔案打包為 ZIP 壓縮檔。" + }, + "comparePdfs": { + "name": "比較 PDF", + "subtitle": "並排比較兩個 PDF。" + }, + "posterizePdf": { + "name": "海報化 PDF", + "subtitle": "將大頁面分割為多個較小的頁面。" + }, + "fixPageSize": { + "name": "修復頁面大小", + "subtitle": "將所有頁面標準化為統一尺寸。" + }, + "linearizePdf": { + "name": "線性化 PDF", + "subtitle": "為快速網頁瀏覽優化 PDF。" + }, + "pageDimensions": { + "name": "頁面尺寸", + "subtitle": "分析頁面大小、方向和單位。" + }, + "removeRestrictions": { + "name": "移除限制", + "subtitle": "移除與數位簽名的 PDF 檔案相關的密碼保護與安全限制。" + }, + "repairPdf": { + "name": "修復 PDF", + "subtitle": "從受損的 PDF 檔案中復原資料。" + }, + "encryptPdf": { + "name": "加密 PDF", + "subtitle": "透過添加密碼為你的 PDF 上鎖。" + }, + "sanitizePdf": { + "name": "清理 PDF", + "subtitle": "移除元資料、註解、腳本與其他資料。" + }, + "decryptPdf": { + "name": "解密 PDF", + "subtitle": "透過移除密碼保護解鎖 PDF。" + }, + "flattenPdf": { + "name": "平面化 PDF", + "subtitle": "使表單欄位和註解不可編輯。" + }, + "removeMetadata": { + "name": "移除元資料", + "subtitle": "除去你的 PDF 中的隱藏資料。" + }, + "changePermissions": { + "name": "更改權限", + "subtitle": "設定或變更 PDF 上的使用者權限。" + }, + "emailToPdf": { + "name": "Email 轉 PDF", + "subtitle": "將電子郵件檔案 (EML, MSG) 轉換為 PDF 格式。支援 Outlook 匯出和標準電子郵件格式。", + "acceptedFormats": "EML, MSG 檔案", + "convertButton": "轉換為 PDF" + }, + "fontToOutline": { + "name": "字型轉外框", + "subtitle": "將所有字型轉換為向量外框,確保在所有裝置上呈現一致。" + }, + "deskewPdf": { + "name": "PDF 歪斜修正", + "subtitle": "使用 OpenCV 自動調正傾斜的掃描頁面。" + }, + "rotateCustom": { + "name": "Rotate by Custom Degrees", + "subtitle": "Rotate pages by any custom angle." + }, + "odtToPdf": { + "name": "ODT to PDF", + "subtitle": "Convert OpenDocument Text files to PDF format. Supports multiple files.", + "acceptedFormats": "ODT files", + "convertButton": "Convert to PDF" + }, + "csvToPdf": { + "name": "CSV to PDF", + "subtitle": "Convert CSV spreadsheet files to PDF format. Supports multiple files.", + "acceptedFormats": "CSV files", + "convertButton": "Convert to PDF" + }, + "rtfToPdf": { + "name": "RTF to PDF", + "subtitle": "Convert Rich Text Format documents to PDF. Supports multiple files.", + "acceptedFormats": "RTF files", + "convertButton": "Convert to PDF" + }, + "wordToPdf": { + "name": "Word to PDF", + "subtitle": "Convert Word documents (DOCX, DOC, ODT, RTF) to PDF format. Supports multiple files.", + "acceptedFormats": "DOCX, DOC, ODT, RTF files", + "convertButton": "Convert to PDF" + }, + "excelToPdf": { + "name": "Excel to PDF", + "subtitle": "Convert Excel spreadsheets (XLSX, XLS, ODS, CSV) to PDF format. Supports multiple files.", + "acceptedFormats": "XLSX, XLS, ODS, CSV files", + "convertButton": "Convert to PDF" + }, + "powerpointToPdf": { + "name": "PowerPoint to PDF", + "subtitle": "Convert PowerPoint presentations (PPTX, PPT, ODP) to PDF format. Supports multiple files.", + "acceptedFormats": "PPTX, PPT, ODP files", + "convertButton": "Convert to PDF" + }, + "markdownToPdf": { + "name": "Markdown to PDF", + "subtitle": "Write or paste Markdown and export it as a beautifully formatted PDF.", + "paneMarkdown": "Markdown", + "panePreview": "Preview", + "btnUpload": "Upload", + "btnSyncScroll": "Sync Scroll", + "btnSettings": "Settings", + "btnExportPdf": "Export PDF", + "settingsTitle": "Markdown Settings", + "settingsPreset": "Preset", + "presetDefault": "Default (GFM-like)", + "presetCommonmark": "CommonMark (strict)", + "presetZero": "Minimal (no features)", + "settingsOptions": "Markdown Options", + "optAllowHtml": "Allow HTML tags", + "optBreaks": "Convert newlines to
", + "optLinkify": "Auto-convert URLs to links", + "optTypographer": "Typographer (smart quotes, etc.)" + }, + "pdfBooklet": { + "name": "PDF Booklet", + "subtitle": "Rearrange pages for double-sided booklet printing. Fold and staple to create a booklet.", + "howItWorks": "How it works:", + "step1": "Upload a PDF file.", + "step2": "Pages will be rearranged in booklet order.", + "step3": "Print double-sided, flip on short edge, fold and staple.", + "paperSize": "Paper Size", + "orientation": "Orientation", + "portrait": "Portrait", + "landscape": "Landscape", + "pagesPerSheet": "Pages per Sheet", + "createBooklet": "Create Booklet", + "processing": "Processing...", + "pageCount": "Page count will be padded to multiple of 4 if needed." + }, + "xpsToPdf": { + "name": "XPS to PDF", + "subtitle": "Convert XPS/OXPS documents to PDF format. Supports multiple files.", + "acceptedFormats": "XPS, OXPS files", + "convertButton": "Convert to PDF" + }, + "mobiToPdf": { + "name": "MOBI to PDF", + "subtitle": "Convert MOBI e-books to PDF format. Supports multiple files.", + "acceptedFormats": "MOBI files", + "convertButton": "Convert to PDF" + }, + "epubToPdf": { + "name": "EPUB to PDF", + "subtitle": "Convert EPUB e-books to PDF format. Supports multiple files.", + "acceptedFormats": "EPUB files", + "convertButton": "Convert to PDF" + }, + "fb2ToPdf": { + "name": "FB2 to PDF", + "subtitle": "Convert FictionBook (FB2) e-books to PDF format. Supports multiple files.", + "acceptedFormats": "FB2 files", + "convertButton": "Convert to PDF" + }, + "cbzToPdf": { + "name": "CBZ to PDF", + "subtitle": "Convert comic book archives (CBZ/CBR) to PDF format. Supports multiple files.", + "acceptedFormats": "CBZ, CBR files", + "convertButton": "Convert to PDF" + }, + "wpdToPdf": { + "name": "WPD to PDF", + "subtitle": "Convert WordPerfect documents (WPD) to PDF format. Supports multiple files.", + "acceptedFormats": "WPD files", + "convertButton": "Convert to PDF" + }, + "wpsToPdf": { + "name": "WPS to PDF", + "subtitle": "Convert WPS Office documents to PDF format. Supports multiple files.", + "acceptedFormats": "WPS files", + "convertButton": "Convert to PDF" + }, + "xmlToPdf": { + "name": "XML to PDF", + "subtitle": "Convert XML documents to PDF format. Supports multiple files.", + "acceptedFormats": "XML files", + "convertButton": "Convert to PDF" + }, + "pagesToPdf": { + "name": "Pages to PDF", + "subtitle": "Convert Apple Pages documents to PDF format. Supports multiple files.", + "acceptedFormats": "Pages files", + "convertButton": "Convert to PDF" + }, + "odgToPdf": { + "name": "ODG to PDF", + "subtitle": "Convert OpenDocument Graphics (ODG) files to PDF format. Supports multiple files.", + "acceptedFormats": "ODG files", + "convertButton": "Convert to PDF" + }, + "odsToPdf": { + "name": "ODS to PDF", + "subtitle": "Convert OpenDocument Spreadsheet (ODS) files to PDF format. Supports multiple files.", + "acceptedFormats": "ODS files", + "convertButton": "Convert to PDF" + }, + "odpToPdf": { + "name": "ODP to PDF", + "subtitle": "Convert OpenDocument Presentation (ODP) files to PDF format. Supports multiple files.", + "acceptedFormats": "ODP files", + "convertButton": "Convert to PDF" + }, + "pubToPdf": { + "name": "PUB to PDF", + "subtitle": "Convert Microsoft Publisher (PUB) files to PDF format. Supports multiple files.", + "acceptedFormats": "PUB files", + "convertButton": "Convert to PDF" + }, + "vsdToPdf": { + "name": "VSD to PDF", + "subtitle": "Convert Microsoft Visio (VSD, VSDX) files to PDF format. Supports multiple files.", + "acceptedFormats": "VSD, VSDX files", + "convertButton": "Convert to PDF" + }, + "psdToPdf": { + "name": "PSD to PDF", + "subtitle": "Convert Adobe Photoshop (PSD) files to PDF format. Supports multiple files.", + "acceptedFormats": "PSD files", + "convertButton": "Convert to PDF" + }, + "pdfToSvg": { + "name": "PDF to SVG", + "subtitle": "Convert each page of a PDF file into a scalable vector graphic (SVG) for perfect quality at any size." + }, + "extractTables": { + "name": "Extract PDF Tables", + "subtitle": "Extract tables from PDF files and export as CSV, JSON, or Markdown." + }, + "pdfToCsv": { + "name": "PDF to CSV", + "subtitle": "Extract tables from PDF and convert to CSV format." + }, + "pdfToExcel": { + "name": "PDF to Excel", + "subtitle": "Extract tables from PDF and convert to Excel (XLSX) format." + }, + "pdfToText": { + "name": "PDF to Text", + "subtitle": "Extract text from PDF files and save as plain text (.txt). Supports multiple files.", + "note": "This tool works ONLY with digitally created PDFs. For scanned documents or image-based PDFs, use our OCR PDF tool instead.", + "convertButton": "Extract Text" + }, + "digitalSignPdf": { + "name": "Digital Signature PDF", + "pageTitle": "Digital Signature PDF - Add Cryptographic Signature | BentoPDF", + "subtitle": "Add a cryptographic digital signature to your PDF using X.509 certificates. Supports PKCS#12 (.pfx, .p12) and PEM formats. Your private key never leaves your browser.", + "certificateSection": "Certificate", + "uploadCert": "Upload certificate (.pfx, .p12)", + "certPassword": "Certificate Password", + "certPasswordPlaceholder": "Enter certificate password", + "certInfo": "Certificate Information", + "certSubject": "Subject", + "certIssuer": "Issuer", + "certValidity": "Valid", + "signatureDetails": "Signature Details (Optional)", + "reason": "Reason", + "reasonPlaceholder": "e.g., I approve this document", + "location": "Location", + "locationPlaceholder": "e.g., New York, USA", + "contactInfo": "Contact Info", + "contactPlaceholder": "e.g., email@example.com", + "applySignature": "Apply Digital Signature", + "successMessage": "PDF signed successfully! The signature can be verified in any PDF reader." + }, + "validateSignaturePdf": { + "name": "Validate PDF Signature", + "pageTitle": "Validate PDF Signature - Verify Digital Signatures | BentoPDF", + "subtitle": "Verify digital signatures in your PDF files. Check certificate validity, view signer details, and confirm document integrity. All processing happens in your browser." + } +} diff --git a/public/locales/zh/common.json b/public/locales/zh/common.json index a65fed9..9fe300b 100644 --- a/public/locales/zh/common.json +++ b/public/locales/zh/common.json @@ -1,318 +1,323 @@ { - "nav": { - "home": "首页", - "about": "关于我们", - "contact": "联系我们", - "licensing": "许可", - "allTools": "所有工具", - "openMainMenu": "打开主菜单", - "language": "语言" + "nav": { + "home": "首页", + "about": "关于我们", + "contact": "联系我们", + "licensing": "许可", + "allTools": "所有工具", + "openMainMenu": "打开主菜单", + "language": "语言" + }, + "donation": { + "message": "喜欢 BentoPDF?帮助我们保持免费和开源!", + "button": "捐赠" + }, + "hero": { + "title": "专为隐私打造的", + "pdfToolkit": "PDF 工具箱", + "builtForPrivacy": " ", + "noSignups": "无需注册", + "unlimitedUse": "无限使用", + "worksOffline": "离线可用", + "startUsing": "立即开始" + }, + "usedBy": { + "title": "被众多公司和个人信赖,包括" + }, + "features": { + "title": "为什么选择", + "bentoPdf": "BentoPDF?", + "noSignup": { + "title": "无需注册", + "description": "即刻开始,无需账户或电子邮件。" }, - "hero": { - "title": "专为隐私打造的", - "pdfToolkit": "PDF 工具箱", - "builtForPrivacy": " ", - "noSignups": "无需注册", - "unlimitedUse": "无限使用", - "worksOffline": "离线可用", - "startUsing": "立即开始" + "noUploads": { + "title": "无需上传", + "description": "100% 客户端处理,您的文件从未离开您的设备。" }, - "usedBy": { - "title": "被众多公司和个人信赖,包括" + "foreverFree": { + "title": "永久免费", + "description": "所有工具免费,无试用期,无付费墙。" }, - "features": { - "title": "为什么选择", - "bentoPdf": "BentoPDF?", - "noSignup": { - "title": "无需注册", - "description": "即刻开始,无需账户或电子邮件。" - }, - "noUploads": { - "title": "无需上传", - "description": "100% 客户端处理,您的文件从未离开您的设备。" - }, - "foreverFree": { - "title": "永久免费", - "description": "所有工具免费,无试用期,无付费墙。" - }, - "noLimits": { - "title": "无限制", - "description": "随心使用,无任何隐形限制。" - }, - "batchProcessing": { - "title": "批量处理", - "description": "一次处理无限数量的 PDF 文件。" - }, - "lightningFast": { - "title": "极速处理", - "description": "瞬间处理 PDF, 无需等待。" - } + "noLimits": { + "title": "无限制", + "description": "随心使用,无任何隐形限制。" }, - "tools": { - "title": "开始使用", - "toolsLabel": "工具", - "subtitle": "点击工具以打开文件上传", - "searchPlaceholder": "搜索工具 (例如 '合并', '分割'...)", - "backToTools": "返回工具列表" + "batchProcessing": { + "title": "批量处理", + "description": "一次处理无限数量的 PDF 文件。" }, - "upload": { - "clickToSelect": "点击选择文件", - "orDragAndDrop": "或将文件拖放到此处", - "pdfOrImages": "PDF 或图片", - "filesNeverLeave": "您的文件从未离开您的设备。", - "addMore": "添加更多文件", - "clearAll": "清空所有" - }, - "loader": { - "processing": "处理中..." - }, - "alert": { - "title": "提示", - "ok": "确定" - }, - "preview": { - "title": "文档预览", - "downloadAsPdf": "下载 PDF", - "close": "关闭" - }, - "settings": { - "title": "设置", - "shortcuts": "快捷键", - "preferences": "偏好设置", - "displayPreferences": "显示设置", - "searchShortcuts": "搜索快捷键...", - "shortcutsInfo": "按下并按住按键以设置快捷键。更改将自动保存。", - "shortcutsWarning": "⚠️ 避免使用通用的浏览器快捷键 (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N 等),因为它们可能无法稳定工作。", - "import": "导入", - "export": "导出", - "resetToDefaults": "恢复默认", - "fullWidthMode": "全宽模式", - "fullWidthDescription": "使用全屏宽度展示所有工具,而非居中显示", - "settingsAutoSaved": "设置已自动保存", - "clickToSet": "点击设置", - "pressKeys": "按下按键...", - "warnings": { - "alreadyInUse": "快捷键已被使用", - "assignedTo": "已分配给:", - "chooseDifferent": "请选择其他快捷键。", - "reserved": "保留快捷键警告", - "commonlyUsed": "通常用于:", - "unreliable": "此快捷键可能无法稳定工作,或与浏览器/系统快捷键冲突。", - "useAnyway": "仍要使用吗?", - "resetTitle": "重置快捷键", - "resetMessage": "确定要将所有快捷键重置为默认值吗?

此操作无法撤销。", - "importSuccessTitle": "导入成功", - "importSuccessMessage": "快捷键导入成功!", - "importFailTitle": "导入失败", - "importFailMessage": "导入快捷键失败。文件格式无效。" - } - }, - "warning": { - "title": "警告", - "cancel": "取消", - "proceed": "继续" - }, - "compliance": { - "title": "您的数据从未离开您的设备", - "weKeep": "我们会保持", - "yourInfoSafe": "您的信息安全", - "byFollowingStandards": ",遵循全球安全标准。", - "processingLocal": "所有处理都在您的设备上本地进行。", - "gdpr": { - "title": "GDPR 合规", - "description": "保护欧盟境内个人的个人数据和隐私。" - }, - "ccpa": { - "title": "CCPA 合规", - "description": "赋予加州居民对其个人信息的收集、使用和共享的权利。" - }, - "hipaa": { - "title": "HIPAA 合规", - "description": "制定美国医疗系统中处理敏感健康信息的保障措施。" - } - }, - "faq": { - "title": "常见", - "questions": "问题", - "isFree": { - "question": "BentoPDF 真的免费吗?", - "answer": "是的,完全免费。BentoPDF 上的所有工具均可 100% 免费使用,没有文件限制,无需注册,也没有水印。我们相信每个人都应该能够使用简单、强大的 PDF 工具,而无需通过付费墙。" - }, - "areFilesSecure": { - "question": "我的文件安全吗?它们在哪里处理?", - "answer": "您的文件非常安全,因为它们从未离开您的电脑。所有处理都直接在您的网络浏览器(客户端)中进行。我们从不将您的文件上传到服务器,因此您可以对文档保持完全的隐私和控制。" - }, - "platforms": { - "question": "它适用于 Mac、Windows 和手机吗?", - "answer": "是的!由于 BentoPDF 完全在您的浏览器中运行,因此它适用于任何带有现代网络浏览器的操作系统,包括 Windows、macOS、Linux、iOS 和 Android。" - }, - "gdprCompliant": { - "question": "BentoPDF 符合 GDPR 吗?", - "answer": "是的。BentoPDF 完全符合 GDPR。由于所有文件处理都在您的浏览器中本地进行,并且我们从不收集或将您的文件传输到任何服务器,因此我们无法访问您的数据。这确保您始终掌控您的文档。" - }, - "dataStorage": { - "question": "你们会存储或跟踪我的任何文件吗?", - "answer": "不。我们从不存储、跟踪或记录您的文件。您在 BentoPDF 上所做的所有操作都在您的浏览器内存中进行,并在您关闭页面后消失。没有上传,没有历史记录,也没有涉及服务器。" - }, - "different": { - "question": "BentoPDF 与其他 PDF 工具有何不同?", - "answer": "大多数 PDF 工具将您的文件上传到服务器进行处理。BentoPDF 从不这样做。我们使用安全、现代的网络技术直接在您的浏览器中处理您的文件。这意味着更快的性能、更强的隐私和完全的安心。" - }, - "browserBased": { - "question": "基于浏览器的处理如何保护我的安全?", - "answer": "通过完全在您的浏览器内部运行,BentoPDF 确保您的文件从未离开您的设备。这消除了服务器黑客攻击、数据泄露或未经授权访问的风险。您的文件始终属于您。" - }, - "analytics": { - "question": "你们使用 Cookie 或分析来跟踪我吗?", - "answer": "我们关心您的隐私。BentoPDF 不会跟踪个人信息。我们仅使用 Simple Analytics 查看匿名访问计数。这意味着我们可以知道有多少用户访问我们的网站,但我们永远不知道您是谁。Simple Analytics 完全符合 GDPR 并尊重您的隐私。" - } - }, - "testimonials": { - "title": "我们的", - "users": "用户", - "say": "评价" - }, - "support": { - "title": "喜欢这个项目?", - "description": "BentoPDF 是一个充满激情的项目,旨在为每个人提供免费、私密且强大的 PDF 工具箱。如果您觉得它有用,请考虑支持它的开发。每一杯咖啡都是莫大的支持!", - "buyMeCoffee": "请我喝杯咖啡" - }, - "footer": { - "copyright": "© 2025 BentoPDF. 保留所有权利。", - "version": "版本", - "company": "公司", - "aboutUs": "关于我们", - "faqLink": "常见问题", - "contactUs": "联系我们", - "legal": "法律", - "termsAndConditions": "服务条款", - "privacyPolicy": "隐私政策", - "followUs": "关注我们" - }, - "merge": { - "title": "合并 PDF", - "description": "合并整个文件,或选择特定页面合并到新文档中。", - "fileMode": "文件模式", - "pageMode": "页面模式", - "howItWorks": "使用说明:", - "fileModeInstructions": [ - "点击并拖动图标以更改文件的顺序。", - "在每个文件的 '页码' 框中,您可以指定范围(例如 '1-3, 5')以仅合并这些页面。", - "将 '页码' 框留空以包含该文件的所有页面。" - ], - "pageModeInstructions": [ - "您上传的 PDF 的所有页面显示在下方。", - "只需拖放单个页面缩略图,即可为您新文件对页面进行排序。" - ], - "mergePdfs": "合并 PDF" - }, - "common": { - "page": "页", - "pages": "页", - "of": " / ", - "download": "下载", - "cancel": "取消", - "save": "保存", - "delete": "删除", - "edit": "编辑", - "add": "添加", - "remove": "移除", - "loading": "加载中...", - "error": "错误", - "success": "成功", - "file": "文件", - "files": "文件" - }, - "about": { - "hero": { - "title": "我们相信 PDF 工具应该是", - "subtitle": "快速、私密且免费的。", - "noCompromises": "绝不妥协。" - }, - "mission": { - "title": "我们的使命", - "description": "提供最全面的 PDF 工具箱,尊重您的隐私,且永不收费。我们相信基本的文档工具应该对所有人、在任何地方都触手可及,没有任何障碍。" - }, - "philosophy": { - "label": "我们的核心理念", - "title": "隐私至上。始终如一。", - "description": "在数据被商品化的时代,我们采取不同的方式。BentoPDF 工具的所有处理都在您的浏览器本地进行。这意味着您的文件从未接触我们的服务器,我们从不查看您的文档,也不跟踪您的操作。您的文档保持绝对的私密性。这不仅是一项功能;这是我们的基石。" - }, - "whyBentopdf": { - "title": "为什么选择", - "speed": { - "title": "为速度而生", - "description": "无需等待上传或从服务器下载。通过使用 WebAssembly 等现代网络技术直接在您的浏览器中处理文件,我们为所有工具提供了无与伦比的速度。" - }, - "free": { - "title": "完全免费", - "description": "无试用,无订阅,无隐藏费用,也没有被锁定的 '高级' 功能。我们相信强大的 PDF 工具应该是一种公共设施,而不是盈利中心。" - }, - "noAccount": { - "title": "无需账户", - "description": "立即开始使用任何工具。我们不需要您的电子邮件、密码或任何个人信息。您的工作流程应该是无摩擦且匿名的。" - }, - "openSource": { - "title": "开源精神", - "description": "以透明度为核心构建。我们利用了像 PDF-lib 和 PDF.js 这样优秀的开源库,并相信社区驱动的力量能使强大的工具惠及每一个人。" - } - }, - "cta": { - "title": "准备好开始了吗?", - "description": "加入成千上万信任 BentoPDF 满足日常文档需求的用户。体验隐私和性能带来的不同。", - "button": "探索所有工具" - } - }, - "contact": { - "title": "联系我们", - "subtitle": "我们很乐意听到您的声音。无论您有问题、反馈还是功能请求,请随时联系我们。", - "email": "您可以直接通过电子邮件联系我们:" - }, - "licensing": { - "title": "许可适用", - "subtitle": "选择适合您需求的许可。" - }, - "multiTool": { - "uploadPdfs": "上传 PDF", - "upload": "上传", - "addBlankPage": "添加空白页", - "edit": "编辑:", - "undo": "撤销", - "redo": "重做", - "reset": "重置", - "selection": "选择:", - "selectAll": "全选", - "deselectAll": "取消全选", - "rotate": "旋转:", - "rotateLeft": "向左", - "rotateRight": "向右", - "transform": "变换:", - "duplicate": "复制", - "split": "拆分", - "clear": "清除:", - "delete": "删除", - "download": "下载:", - "downloadSelected": "下载选中", - "exportPdf": "导出 PDF", - "uploadPdfFiles": "选择 PDF 文件", - "dragAndDrop": "将 PDF 文件拖放到此处,或点击选择", - "selectFiles": "选择文件", - "renderingPages": "正在渲染页面...", - "actions": { - "duplicatePage": "复制此页", - "deletePage": "删除此页", - "insertPdf": "在此页后插入 PDF", - "toggleSplit": "在此页后切换拆分" - }, - "pleaseWait": "请稍候", - "pagesRendering": "页面正在渲染中,请稍候...", - "noPagesSelected": "未选择页面", - "selectOnePage": "请至少选择一页以进行下载。", - "noPages": "没有页面", - "noPagesToExport": "没有可导出的页面。", - "renderingTitle": "正在渲染页面预览", - "errorRendering": "渲染页面缩略图失败", - "error": "错误", - "failedToLoad": "加载失败" + "lightningFast": { + "title": "极速处理", + "description": "瞬间处理 PDF, 无需等待。" } -} \ No newline at end of file + }, + "tools": { + "title": "开始使用", + "toolsLabel": "工具", + "subtitle": "点击工具以打开文件上传", + "searchPlaceholder": "搜索工具 (例如 '合并', '分割'...)", + "backToTools": "返回工具列表", + "firstLoadNotice": "首次加载需要一点时间,因为我们正在下载转换引擎。之后所有加载将即时完成。" + }, + "upload": { + "clickToSelect": "点击选择文件", + "orDragAndDrop": "或将文件拖放到此处", + "pdfOrImages": "PDF 或图片", + "filesNeverLeave": "您的文件从未离开您的设备。", + "addMore": "添加更多文件", + "clearAll": "清空所有" + }, + "loader": { + "processing": "处理中..." + }, + "alert": { + "title": "提示", + "ok": "确定" + }, + "preview": { + "title": "文档预览", + "downloadAsPdf": "下载 PDF", + "close": "关闭" + }, + "settings": { + "title": "设置", + "shortcuts": "快捷键", + "preferences": "偏好设置", + "displayPreferences": "显示设置", + "searchShortcuts": "搜索快捷键...", + "shortcutsInfo": "按下并按住按键以设置快捷键。更改将自动保存。", + "shortcutsWarning": "⚠️ 避免使用通用的浏览器快捷键 (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N 等),因为它们可能无法稳定工作。", + "import": "导入", + "export": "导出", + "resetToDefaults": "恢复默认", + "fullWidthMode": "全宽模式", + "fullWidthDescription": "使用全屏宽度展示所有工具,而非居中显示", + "settingsAutoSaved": "设置已自动保存", + "clickToSet": "点击设置", + "pressKeys": "按下按键...", + "warnings": { + "alreadyInUse": "快捷键已被使用", + "assignedTo": "已分配给:", + "chooseDifferent": "请选择其他快捷键。", + "reserved": "保留快捷键警告", + "commonlyUsed": "通常用于:", + "unreliable": "此快捷键可能无法稳定工作,或与浏览器/系统快捷键冲突。", + "useAnyway": "仍要使用吗?", + "resetTitle": "重置快捷键", + "resetMessage": "确定要将所有快捷键重置为默认值吗?

此操作无法撤销。", + "importSuccessTitle": "导入成功", + "importSuccessMessage": "快捷键导入成功!", + "importFailTitle": "导入失败", + "importFailMessage": "导入快捷键失败。文件格式无效。" + } + }, + "warning": { + "title": "警告", + "cancel": "取消", + "proceed": "继续" + }, + "compliance": { + "title": "您的数据从未离开您的设备", + "weKeep": "我们会保持", + "yourInfoSafe": "您的信息安全", + "byFollowingStandards": ",遵循全球安全标准。", + "processingLocal": "所有处理都在您的设备上本地进行。", + "gdpr": { + "title": "GDPR 合规", + "description": "保护欧盟境内个人的个人数据和隐私。" + }, + "ccpa": { + "title": "CCPA 合规", + "description": "赋予加州居民对其个人信息的收集、使用和共享的权利。" + }, + "hipaa": { + "title": "HIPAA 合规", + "description": "制定美国医疗系统中处理敏感健康信息的保障措施。" + } + }, + "faq": { + "title": "常见", + "questions": "问题", + "isFree": { + "question": "BentoPDF 真的免费吗?", + "answer": "是的,完全免费。BentoPDF 上的所有工具均可 100% 免费使用,没有文件限制,无需注册,也没有水印。我们相信每个人都应该能够使用简单、强大的 PDF 工具,而无需通过付费墙。" + }, + "areFilesSecure": { + "question": "我的文件安全吗?它们在哪里处理?", + "answer": "您的文件非常安全,因为它们从未离开您的电脑。所有处理都直接在您的网络浏览器(客户端)中进行。我们从不将您的文件上传到服务器,因此您可以对文档保持完全的隐私和控制。" + }, + "platforms": { + "question": "它适用于 Mac、Windows 和手机吗?", + "answer": "是的!由于 BentoPDF 完全在您的浏览器中运行,因此它适用于任何带有现代网络浏览器的操作系统,包括 Windows、macOS、Linux、iOS 和 Android。" + }, + "gdprCompliant": { + "question": "BentoPDF 符合 GDPR 吗?", + "answer": "是的。BentoPDF 完全符合 GDPR。由于所有文件处理都在您的浏览器中本地进行,并且我们从不收集或将您的文件传输到任何服务器,因此我们无法访问您的数据。这确保您始终掌控您的文档。" + }, + "dataStorage": { + "question": "你们会存储或跟踪我的任何文件吗?", + "answer": "不。我们从不存储、跟踪或记录您的文件。您在 BentoPDF 上所做的所有操作都在您的浏览器内存中进行,并在您关闭页面后消失。没有上传,没有历史记录,也没有涉及服务器。" + }, + "different": { + "question": "BentoPDF 与其他 PDF 工具有何不同?", + "answer": "大多数 PDF 工具将您的文件上传到服务器进行处理。BentoPDF 从不这样做。我们使用安全、现代的网络技术直接在您的浏览器中处理您的文件。这意味着更快的性能、更强的隐私和完全的安心。" + }, + "browserBased": { + "question": "基于浏览器的处理如何保护我的安全?", + "answer": "通过完全在您的浏览器内部运行,BentoPDF 确保您的文件从未离开您的设备。这消除了服务器黑客攻击、数据泄露或未经授权访问的风险。您的文件始终属于您。" + }, + "analytics": { + "question": "你们使用 Cookie 或分析来跟踪我吗?", + "answer": "我们关心您的隐私。BentoPDF 不会跟踪个人信息。我们仅使用 Simple Analytics 查看匿名访问计数。这意味着我们可以知道有多少用户访问我们的网站,但我们永远不知道您是谁。Simple Analytics 完全符合 GDPR 并尊重您的隐私。" + } + }, + "testimonials": { + "title": "我们的", + "users": "用户", + "say": "评价" + }, + "support": { + "title": "喜欢这个项目?", + "description": "BentoPDF 是一个充满激情的项目,旨在为每个人提供免费、私密且强大的 PDF 工具箱。如果您觉得它有用,请考虑支持它的开发。每一杯咖啡都是莫大的支持!", + "buyMeCoffee": "请我喝杯咖啡" + }, + "footer": { + "copyright": "© 2026 BentoPDF. 保留所有权利。", + "version": "版本", + "company": "公司", + "aboutUs": "关于我们", + "faqLink": "常见问题", + "contactUs": "联系我们", + "legal": "法律", + "termsAndConditions": "服务条款", + "privacyPolicy": "隐私政策", + "followUs": "关注我们" + }, + "merge": { + "title": "合并 PDF", + "description": "合并整个文件,或选择特定页面合并到新文档中。", + "fileMode": "文件模式", + "pageMode": "页面模式", + "howItWorks": "使用说明:", + "fileModeInstructions": [ + "点击并拖动图标以更改文件的顺序。", + "在每个文件的 '页码' 框中,您可以指定范围(例如 '1-3, 5')以仅合并这些页面。", + "将 '页码' 框留空以包含该文件的所有页面。" + ], + "pageModeInstructions": [ + "您上传的 PDF 的所有页面显示在下方。", + "只需拖放单个页面缩略图,即可为您新文件对页面进行排序。" + ], + "mergePdfs": "合并 PDF" + }, + "common": { + "page": "页", + "pages": "页", + "of": " / ", + "download": "下载", + "cancel": "取消", + "save": "保存", + "delete": "删除", + "edit": "编辑", + "add": "添加", + "remove": "移除", + "loading": "加载中...", + "error": "错误", + "success": "成功", + "file": "文件", + "files": "文件" + }, + "about": { + "hero": { + "title": "我们相信 PDF 工具应该是", + "subtitle": "快速、私密且免费的。", + "noCompromises": "绝不妥协。" + }, + "mission": { + "title": "我们的使命", + "description": "提供最全面的 PDF 工具箱,尊重您的隐私,且永不收费。我们相信基本的文档工具应该对所有人、在任何地方都触手可及,没有任何障碍。" + }, + "philosophy": { + "label": "我们的核心理念", + "title": "隐私至上。始终如一。", + "description": "在数据被商品化的时代,我们采取不同的方式。BentoPDF 工具的所有处理都在您的浏览器本地进行。这意味着您的文件从未接触我们的服务器,我们从不查看您的文档,也不跟踪您的操作。您的文档保持绝对的私密性。这不仅是一项功能;这是我们的基石。" + }, + "whyBentopdf": { + "title": "为什么选择", + "speed": { + "title": "为速度而生", + "description": "无需等待上传或从服务器下载。通过使用 WebAssembly 等现代网络技术直接在您的浏览器中处理文件,我们为所有工具提供了无与伦比的速度。" + }, + "free": { + "title": "完全免费", + "description": "无试用,无订阅,无隐藏费用,也没有被锁定的 '高级' 功能。我们相信强大的 PDF 工具应该是一种公共设施,而不是盈利中心。" + }, + "noAccount": { + "title": "无需账户", + "description": "立即开始使用任何工具。我们不需要您的电子邮件、密码或任何个人信息。您的工作流程应该是无摩擦且匿名的。" + }, + "openSource": { + "title": "开源精神", + "description": "以透明度为核心构建。我们利用了像 PDF-lib 和 PDF.js 这样优秀的开源库,并相信社区驱动的力量能使强大的工具惠及每一个人。" + } + }, + "cta": { + "title": "准备好开始了吗?", + "description": "加入成千上万信任 BentoPDF 满足日常文档需求的用户。体验隐私和性能带来的不同。", + "button": "探索所有工具" + } + }, + "contact": { + "title": "联系我们", + "subtitle": "我们很乐意听到您的声音。无论您有问题、反馈还是功能请求,请随时联系我们。", + "email": "您可以直接通过电子邮件联系我们:" + }, + "licensing": { + "title": "许可适用", + "subtitle": "选择适合您需求的许可。" + }, + "multiTool": { + "uploadPdfs": "上传 PDF", + "upload": "上传", + "addBlankPage": "添加空白页", + "edit": "编辑:", + "undo": "撤销", + "redo": "重做", + "reset": "重置", + "selection": "选择:", + "selectAll": "全选", + "deselectAll": "取消全选", + "rotate": "旋转:", + "rotateLeft": "向左", + "rotateRight": "向右", + "transform": "变换:", + "duplicate": "复制", + "split": "拆分", + "clear": "清除:", + "delete": "删除", + "download": "下载:", + "downloadSelected": "下载选中", + "exportPdf": "导出 PDF", + "uploadPdfFiles": "选择 PDF 文件", + "dragAndDrop": "将 PDF 文件拖放到此处,或点击选择", + "selectFiles": "选择文件", + "renderingPages": "正在渲染页面...", + "actions": { + "duplicatePage": "复制此页", + "deletePage": "删除此页", + "insertPdf": "在此页后插入 PDF", + "toggleSplit": "在此页后切换拆分" + }, + "pleaseWait": "请稍候", + "pagesRendering": "页面正在渲染中,请稍候...", + "noPagesSelected": "未选择页面", + "selectOnePage": "请至少选择一页以进行下载。", + "noPages": "没有页面", + "noPagesToExport": "没有可导出的页面。", + "renderingTitle": "正在渲染页面预览", + "errorRendering": "渲染页面缩略图失败", + "error": "错误", + "failedToLoad": "加载失败" + } +} diff --git a/public/locales/zh/tools.json b/public/locales/zh/tools.json index a64ed0f..a93c822 100644 --- a/public/locales/zh/tools.json +++ b/public/locales/zh/tools.json @@ -1,279 +1,530 @@ { - "categories": { - "popularTools": "热门工具", - "editAnnotate": "编辑与注释", - "convertToPdf": "转换为 PDF", - "convertFromPdf": "从 PDF 转换", - "organizeManage": "组织与管理", - "optimizeRepair": "优化与修复", - "securePdf": "安全 PDF" - }, - "pdfMultiTool": { - "name": "PDF 多功能工具", - "subtitle": "在一个统一的界面中合并、分割、组织、删除、旋转、添加空白页、提取和复制。" - }, - "mergePdf": { - "name": "合并 PDF", - "subtitle": "将多个 PDF 合并为一个文件。保留书签。" - }, - "splitPdf": { - "name": "分割 PDF", - "subtitle": "将指定范围的页面提取到新 PDF 中。" - }, - "compressPdf": { - "name": "压缩 PDF", - "subtitle": "减小您的 PDF 文件大小。" - }, - "pdfEditor": { - "name": "PDF 编辑器", - "subtitle": "注释、高亮、涂黑、评论、添加形状/图片、搜索和查看 PDF。" - }, - "jpgToPdf": { - "name": "JPG 转 PDF", - "subtitle": "从一张或多张 JPG 图片创建 PDF。" - }, - "signPdf": { - "name": "签署 PDF", - "subtitle": "绘制、键入或上传您的签名。" - }, - "cropPdf": { - "name": "裁剪 PDF", - "subtitle": "修剪 PDF 中每一页的边距。" - }, - "extractPages": { - "name": "提取页面", - "subtitle": "将选定的页面保存为新文件。" - }, - "duplicateOrganize": { - "name": "复制与组织", - "subtitle": "复制、重新排序和删除页面。" - }, - "deletePages": { - "name": "删除页面", - "subtitle": "自您的文档中移除特定页面。" - }, - "editBookmarks": { - "name": "编辑书签", - "subtitle": "添加、编辑、导入、删除和提取 PDF 书签。" - }, - "tableOfContents": { - "name": "目录", - "subtitle": "根据 PDF 书签生成目录页。" - }, - "pageNumbers": { - "name": "页码", - "subtitle": "将页码插入到您的文档中。" - }, - "addWatermark": { - "name": "添加水印", - "subtitle": "在您的 PDF 页面上添加文字或图片水印。" - }, - "headerFooter": { - "name": "页眉和页脚", - "subtitle": "在页面顶部和底部添加文字。" - }, - "invertColors": { - "name": "反转颜色", - "subtitle": "创建您的 PDF 的“暗黑模式”版本。" - }, - "backgroundColor": { - "name": "背景颜色", - "subtitle": "更改您的 PDF 的背景颜色。" - }, - "changeTextColor": { - "name": "更改文本颜色", - "subtitle": "更改您 PDF 中文本的颜色。" - }, - "addStamps": { - "name": "添加印章", - "subtitle": "使用注释工具栏向您的 PDF 添加图片印章。" - }, - "removeAnnotations": { - "name": "移除注释", - "subtitle": "移除评论、高亮和链接。" - }, - "pdfFormFiller": { - "name": "PDF 表单填写器", - "subtitle": "直接在浏览器中填写表单。也支持 XFA 表单。" - }, - "createPdfForm": { - "name": "创建 PDF 表单", - "subtitle": "使用拖放文本字段创建可填写的 PDF 表单。" - }, - "removeBlankPages": { - "name": "移除空白页", - "subtitle": "自动检测并删除空白页。" - }, - "imageToPdf": { - "name": "图片转 PDF", - "subtitle": "将 JPG, PNG, WebP, BMP, TIFF, SVG, HEIC 转换为 PDF。" - }, - "pngToPdf": { - "name": "PNG 转 PDF", - "subtitle": "从一张或多张 PNG 图片创建 PDF。" - }, - "webpToPdf": { - "name": "WebP 转 PDF", - "subtitle": "从一张或多张 WebP 图片创建 PDF。" - }, - "svgToPdf": { - "name": "SVG 转 PDF", - "subtitle": "从一张或多张 SVG 图片创建 PDF。" - }, - "bmpToPdf": { - "name": "BMP 转 PDF", - "subtitle": "从一张或多张 BMP 图片创建 PDF。" - }, - "heicToPdf": { - "name": "HEIC 转 PDF", - "subtitle": "从一张或多张 HEIC 图片创建 PDF。" - }, - "tiffToPdf": { - "name": "TIFF 转 PDF", - "subtitle": "从一张或多张 TIFF 图片创建 PDF。" - }, - "textToPdf": { - "name": "文本转 PDF", - "subtitle": "将纯文本文件转换为 PDF。" - }, - "jsonToPdf": { - "name": "JSON 转 PDF", - "subtitle": "将 JSON 文件转换为 PDF 格式。" - }, - "pdfToJpg": { - "name": "PDF 转 JPG", - "subtitle": "将每一页 PDF 转换为 JPG 图片。" - }, - "pdfToPng": { - "name": "PDF 转 PNG", - "subtitle": "将每一页 PDF 转换为 PNG 图片。" - }, - "pdfToWebp": { - "name": "PDF 转 WebP", - "subtitle": "将每一页 PDF 转换为 WebP 图片。" - }, - "pdfToBmp": { - "name": "PDF 转 BMP", - "subtitle": "将每一页 PDF 转换为 BMP 图片。" - }, - "pdfToTiff": { - "name": "PDF 转 TIFF", - "subtitle": "将每一页 PDF 转换为 TIFF 图片。" - }, - "pdfToGreyscale": { - "name": "PDF 转 灰度", - "subtitle": "将所有颜色转换为黑白。" - }, - "pdfToJson": { - "name": "PDF 转 JSON", - "subtitle": "将 PDF 文件转换为 JSON 格式。" - }, - "ocrPdf": { - "name": "OCR PDF", - "subtitle": "使 PDF 可搜索和可复制。" - }, - "alternateMix": { - "name": "交替混合页面", - "subtitle": "通过交替每个 PDF 的页面来合并 PDF。保留书签。" - }, - "addAttachments": { - "name": "添加附件", - "subtitle": "将一个或多个文件嵌入到您的 PDF 中。" - }, - "extractAttachments": { - "name": "提取附件", - "subtitle": "从 PDF 中提取所有嵌入的文件为 ZIP。" - }, - "editAttachments": { - "name": "编辑附件", - "subtitle": "查看或移除 PDF 中的附件。" - }, - "dividePages": { - "name": "分割页面", - "subtitle": "水平或垂直分割页面。" - }, - "addBlankPage": { - "name": "添加空白页", - "subtitle": "在 PDF 的任意位置插入空白页。" - }, - "reversePages": { - "name": "反转页面", - "subtitle": "反转文档中所有页面的顺序。" - }, - "rotatePdf": { - "name": "旋转 PDF", - "subtitle": "以 90 度增量旋转页面。" - }, - "nUpPdf": { - "name": "N-Up PDF", - "subtitle": "将多页排列在单张纸上。" - }, - "combineToSinglePage": { - "name": "合并为单页", - "subtitle": "将所有页面拼接成一个连续的滚动页面。" - }, - "viewMetadata": { - "name": "查看元数据", - "subtitle": "检查 PDF 的隐藏属性。" - }, - "editMetadata": { - "name": "编辑元数据", - "subtitle": "更改作者、标题和其他属性。" - }, - "pdfsToZip": { - "name": "PDF 转 ZIP", - "subtitle": "将多个 PDF 文件打包成一个 ZIP 归档。" - }, - "comparePdfs": { - "name": "比较 PDF", - "subtitle": "并排比较两个 PDF。" - }, - "posterizePdf": { - "name": "海报化 PDF", - "subtitle": "将大页面分割成多个小页面。" - }, - "fixPageSize": { - "name": "修复页面尺寸", - "subtitle": "将所有页面标准化为统一尺寸。" - }, - "linearizePdf": { - "name": "线性化 PDF", - "subtitle": "优化 PDF 以便快速网络查看。" - }, - "pageDimensions": { - "name": "页面尺寸", - "subtitle": "分析页面大小、方向和单位。" - }, - "removeRestrictions": { - "name": "移除限制", - "subtitle": "移除与数字签名 PDF 文件相关的密码保护和安全限制。" - }, - "repairPdf": { - "name": "修复 PDF", - "subtitle": "从损坏的 PDF 文件中恢复数据。" - }, - "encryptPdf": { - "name": "加密 PDF", - "subtitle": "通过添加密码锁定您的 PDF。" - }, - "sanitizePdf": { - "name": "清理 PDF", - "subtitle": "移除元数据、注释、脚本等。" - }, - "decryptPdf": { - "name": "解密 PDF", - "subtitle": "通过移除密码保护解锁 PDF。" - }, - "flattenPdf": { - "name": "扁平化 PDF", - "subtitle": "使表单字段和注释不可编辑。" - }, - "removeMetadata": { - "name": "移除元数据", - "subtitle": "从 PDF 中剥离隐藏数据。" - }, - "changePermissions": { - "name": "更改权限", - "subtitle": "设置或更改 PDF 上的用户权限。" - } -} \ No newline at end of file + "categories": { + "popularTools": "热门工具", + "editAnnotate": "编辑与注释", + "convertToPdf": "转换为 PDF", + "convertFromPdf": "从 PDF 转换", + "organizeManage": "组织与管理", + "optimizeRepair": "优化与修复", + "securePdf": "安全 PDF" + }, + "pdfMultiTool": { + "name": "PDF 多功能工具", + "subtitle": "在一个统一的界面中合并、分割、组织、删除、旋转、添加空白页、提取和复制。" + }, + "mergePdf": { + "name": "合并 PDF", + "subtitle": "将多个 PDF 合并为一个文件。保留书签。" + }, + "splitPdf": { + "name": "分割 PDF", + "subtitle": "将指定范围的页面提取到新 PDF 中。" + }, + "compressPdf": { + "name": "压缩 PDF", + "subtitle": "减小您的 PDF 文件大小。", + "algorithmLabel": "压缩算法", + "condense": "Condense(推荐)", + "photon": "Photon(适用于图片较多的 PDF)", + "condenseInfo": "Condense 使用高级压缩:移除冗余数据、优化图片、精简字体。适用于大多数 PDF。", + "photonInfo": "Photon 将页面转换为图片。适用于图片较多/扫描的 PDF。", + "photonWarning": "警告:文本将无法选择,链接将失效。", + "levelLabel": "压缩级别", + "light": "轻度(保持质量)", + "balanced": "平衡(推荐)", + "aggressive": "积极(更小文件)", + "extreme": "极限(最大压缩)", + "grayscale": "转换为灰度", + "grayscaleHint": "通过移除颜色信息来减小文件大小", + "customSettings": "自定义设置", + "customSettingsHint": "微调压缩参数:", + "outputQuality": "输出质量", + "resizeImagesTo": "调整图片至", + "onlyProcessAbove": "仅处理高于", + "removeMetadata": "移除元数据", + "subsetFonts": "精简字体(移除未使用的字符)", + "removeThumbnails": "移除嵌入的缩略图", + "compressButton": "压缩 PDF" + }, + "pdfEditor": { + "name": "PDF 编辑器", + "subtitle": "注释、高亮、涂黑、评论、添加形状/图片、搜索和查看 PDF。" + }, + "jpgToPdf": { + "name": "JPG 转 PDF", + "subtitle": "从 JPG、JPEG 和 JPEG2000 (JP2/JPX) 图片创建 PDF。" + }, + "signPdf": { + "name": "签署 PDF", + "subtitle": "绘制、键入或上传您的签名。" + }, + "cropPdf": { + "name": "裁剪 PDF", + "subtitle": "修剪 PDF 中每一页的边距。" + }, + "extractPages": { + "name": "提取页面", + "subtitle": "将选定的页面保存为新文件。" + }, + "duplicateOrganize": { + "name": "复制与组织", + "subtitle": "复制、重新排序和删除页面。" + }, + "deletePages": { + "name": "删除页面", + "subtitle": "自您的文档中移除特定页面。" + }, + "editBookmarks": { + "name": "编辑书签", + "subtitle": "添加、编辑、导入、删除和提取 PDF 书签。" + }, + "tableOfContents": { + "name": "目录", + "subtitle": "根据 PDF 书签生成目录页。" + }, + "pageNumbers": { + "name": "页码", + "subtitle": "将页码插入到您的文档中。" + }, + "addWatermark": { + "name": "添加水印", + "subtitle": "在您的 PDF 页面上添加文字或图片水印。" + }, + "headerFooter": { + "name": "页眉和页脚", + "subtitle": "在页面顶部和底部添加文字。" + }, + "invertColors": { + "name": "反转颜色", + "subtitle": "创建您的 PDF 的“暗黑模式”版本。" + }, + "backgroundColor": { + "name": "背景颜色", + "subtitle": "更改您的 PDF 的背景颜色。" + }, + "changeTextColor": { + "name": "更改文本颜色", + "subtitle": "更改您 PDF 中文本的颜色。" + }, + "addStamps": { + "name": "添加印章", + "subtitle": "使用注释工具栏向您的 PDF 添加图片印章。" + }, + "removeAnnotations": { + "name": "移除注释", + "subtitle": "移除评论、高亮和链接。" + }, + "pdfFormFiller": { + "name": "PDF 表单填写器", + "subtitle": "直接在浏览器中填写表单。也支持 XFA 表单。" + }, + "createPdfForm": { + "name": "创建 PDF 表单", + "subtitle": "使用拖放文本字段创建可填写的 PDF 表单。" + }, + "removeBlankPages": { + "name": "移除空白页", + "subtitle": "自动检测并删除空白页。" + }, + "imageToPdf": { + "name": "图片转 PDF", + "subtitle": "将 JPG, PNG, BMP, GIF, TIFF, PNM, PGM, PBM, PPM, PAM, JXR, JPX, JP2, PSD, SVG, HEIC, WebP 转换为 PDF。" + }, + "pngToPdf": { + "name": "PNG 转 PDF", + "subtitle": "从一张或多张 PNG 图片创建 PDF。" + }, + "webpToPdf": { + "name": "WebP 转 PDF", + "subtitle": "从一张或多张 WebP 图片创建 PDF。" + }, + "svgToPdf": { + "name": "SVG 转 PDF", + "subtitle": "从一张或多张 SVG 图片创建 PDF。" + }, + "bmpToPdf": { + "name": "BMP 转 PDF", + "subtitle": "从一张或多张 BMP 图片创建 PDF。" + }, + "heicToPdf": { + "name": "HEIC 转 PDF", + "subtitle": "从一张或多张 HEIC 图片创建 PDF。" + }, + "tiffToPdf": { + "name": "TIFF 转 PDF", + "subtitle": "从一张或多张 TIFF 图片创建 PDF。" + }, + "textToPdf": { + "name": "文本转 PDF", + "subtitle": "将纯文本文件转换为 PDF。" + }, + "jsonToPdf": { + "name": "JSON 转 PDF", + "subtitle": "将 JSON 文件转换为 PDF 格式。" + }, + "pdfToJpg": { + "name": "PDF 转 JPG", + "subtitle": "将每一页 PDF 转换为 JPG 图片。" + }, + "pdfToPng": { + "name": "PDF 转 PNG", + "subtitle": "将每一页 PDF 转换为 PNG 图片。" + }, + "pdfToWebp": { + "name": "PDF 转 WebP", + "subtitle": "将每一页 PDF 转换为 WebP 图片。" + }, + "pdfToBmp": { + "name": "PDF 转 BMP", + "subtitle": "将每一页 PDF 转换为 BMP 图片。" + }, + "pdfToTiff": { + "name": "PDF 转 TIFF", + "subtitle": "将每一页 PDF 转换为 TIFF 图片。" + }, + "pdfToGreyscale": { + "name": "PDF 转 灰度", + "subtitle": "将所有颜色转换为黑白。" + }, + "pdfToJson": { + "name": "PDF 转 JSON", + "subtitle": "将 PDF 文件转换为 JSON 格式。" + }, + "ocrPdf": { + "name": "OCR PDF", + "subtitle": "使 PDF 可搜索和可复制。" + }, + "alternateMix": { + "name": "交替混合页面", + "subtitle": "通过交替每个 PDF 的页面来合并 PDF。保留书签。" + }, + "addAttachments": { + "name": "添加附件", + "subtitle": "将一个或多个文件嵌入到您的 PDF 中。" + }, + "extractAttachments": { + "name": "提取附件", + "subtitle": "从 PDF 中提取所有嵌入的文件为 ZIP。" + }, + "editAttachments": { + "name": "编辑附件", + "subtitle": "查看或移除 PDF 中的附件。" + }, + "dividePages": { + "name": "分割页面", + "subtitle": "水平或垂直分割页面。" + }, + "addBlankPage": { + "name": "添加空白页", + "subtitle": "在 PDF 的任意位置插入空白页。" + }, + "reversePages": { + "name": "反转页面", + "subtitle": "反转文档中所有页面的顺序。" + }, + "rotatePdf": { + "name": "旋转 PDF", + "subtitle": "以 90 度增量旋转页面。" + }, + "rotateCustom": { + "name": "按自定义角度旋转", + "subtitle": "按任意自定义角度旋转页面。" + }, + "nUpPdf": { + "name": "N-Up PDF", + "subtitle": "将多页排列在单张纸上。" + }, + "combineToSinglePage": { + "name": "合并为单页", + "subtitle": "将所有页面拼接成一个连续的滚动页面。" + }, + "viewMetadata": { + "name": "查看元数据", + "subtitle": "检查 PDF 的隐藏属性。" + }, + "editMetadata": { + "name": "编辑元数据", + "subtitle": "更改作者、标题和其他属性。" + }, + "pdfsToZip": { + "name": "PDF 转 ZIP", + "subtitle": "将多个 PDF 文件打包成一个 ZIP 归档。" + }, + "comparePdfs": { + "name": "比较 PDF", + "subtitle": "并排比较两个 PDF。" + }, + "posterizePdf": { + "name": "海报化 PDF", + "subtitle": "将大页面分割成多个小页面。" + }, + "fixPageSize": { + "name": "修复页面尺寸", + "subtitle": "将所有页面标准化为统一尺寸。" + }, + "linearizePdf": { + "name": "线性化 PDF", + "subtitle": "优化 PDF 以便快速网络查看。" + }, + "pageDimensions": { + "name": "页面尺寸", + "subtitle": "分析页面大小、方向和单位。" + }, + "removeRestrictions": { + "name": "移除限制", + "subtitle": "移除与数字签名 PDF 文件相关的密码保护和安全限制。" + }, + "repairPdf": { + "name": "修复 PDF", + "subtitle": "从损坏的 PDF 文件中恢复数据。" + }, + "encryptPdf": { + "name": "加密 PDF", + "subtitle": "通过添加密码锁定您的 PDF。" + }, + "sanitizePdf": { + "name": "清理 PDF", + "subtitle": "移除元数据、注释、脚本等。" + }, + "decryptPdf": { + "name": "解密 PDF", + "subtitle": "通过移除密码保护解锁 PDF。" + }, + "flattenPdf": { + "name": "扁平化 PDF", + "subtitle": "使表单字段和注释不可编辑。" + }, + "removeMetadata": { + "name": "移除元数据", + "subtitle": "从 PDF 中剥离隐藏数据。" + }, + "changePermissions": { + "name": "更改权限", + "subtitle": "设置或更改 PDF 上的用户权限。" + }, + "odtToPdf": { + "name": "ODT 转 PDF", + "subtitle": "将 OpenDocument 文本文件转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "ODT 文件", + "convertButton": "转换为 PDF" + }, + "csvToPdf": { + "name": "CSV 转 PDF", + "subtitle": "将 CSV 电子表格文件转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "CSV 件", + "convertButton": "转换为 PDF" + }, + "rtfToPdf": { + "name": "RTF 转 PDF", + "subtitle": "将富文本格式文档转换为 PDF。支持多个文件。", + "acceptedFormats": "RTF 文件", + "convertButton": "转换为 PDF" + }, + "wordToPdf": { + "name": "Word 转 PDF", + "subtitle": "将 Word 文档 (DOCX, DOC, ODT, RTF) 转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "DOCX, DOC, ODT, RTF 文件", + "convertButton": "转换为 PDF" + }, + "excelToPdf": { + "name": "Excel 转 PDF", + "subtitle": "将 Excel 电子表格 (XLSX, XLS, ODS, CSV) 转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "XLSX, XLS, ODS, CSV 文件", + "convertButton": "转换为 PDF" + }, + "powerpointToPdf": { + "name": "PowerPoint 转 PDF", + "subtitle": "将 PowerPoint 演示文稿 (PPTX, PPT, ODP) 转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "PPTX, PPT, ODP 文件", + "convertButton": "转换为 PDF" + }, + "markdownToPdf": { + "name": "Markdown 转 PDF", + "subtitle": "编写或粘贴 Markdown 并将其导出为精美格式的 PDF。", + "paneMarkdown": "Markdown", + "panePreview": "预览", + "btnUpload": "上传", + "btnSyncScroll": "同步滚动", + "btnSettings": "设置", + "btnExportPdf": "导出 PDF", + "settingsTitle": "Markdown 设置", + "settingsPreset": "预设", + "presetDefault": "默认 (GFM 风格)", + "presetCommonmark": "CommonMark (严格)", + "presetZero": "最小 (无功能)", + "settingsOptions": "Markdown 选项", + "optAllowHtml": "允许 HTML 标签", + "optBreaks": "将换行转换为
", + "optLinkify": "自动将 URL 转换为链接", + "optTypographer": "排版器 (智能引号等)" + }, + "pdfBooklet": { + "name": "PDF 小册子", + "subtitle": "重新排列页面用于双面小册子打印。折叠并装订以创建小册子。", + "howItWorks": "工作原理:", + "step1": "上传 PDF 文件。", + "step2": "页面将按小册子顺序重新排列。", + "step3": "双面打印,短边翻转,折叠并装订。", + "paperSize": "纸张大小", + "orientation": "方向", + "portrait": "纵向", + "landscape": "横向", + "pagesPerSheet": "每张页数", + "createBooklet": "创建小册子", + "processing": "处理中...", + "pageCount": "如需要,页数将补齐为 4 的倍数。" + }, + "xpsToPdf": { + "name": "XPS 转 PDF", + "subtitle": "将 XPS/OXPS 文档转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "XPS, OXPS 文件", + "convertButton": "转换为 PDF" + }, + "mobiToPdf": { + "name": "MOBI 转 PDF", + "subtitle": "将 MOBI 电子书转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "MOBI 文件", + "convertButton": "转换为 PDF" + }, + "epubToPdf": { + "name": "EPUB 转 PDF", + "subtitle": "将 EPUB 电子书转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "EPUB 文件", + "convertButton": "转换为 PDF" + }, + "fb2ToPdf": { + "name": "FB2 转 PDF", + "subtitle": "将 FictionBook (FB2) 电子书转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "FB2 文件", + "convertButton": "转换为 PDF" + }, + "cbzToPdf": { + "name": "CBZ 转 PDF", + "subtitle": "将漫画档案 (CBZ/CBR) 转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "CBZ, CBR 文件", + "convertButton": "转换为 PDF" + }, + "wpdToPdf": { + "name": "WPD 转 PDF", + "subtitle": "将 WordPerfect 文档 (WPD) 转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "WPD 文件", + "convertButton": "转换为 PDF" + }, + "wpsToPdf": { + "name": "WPS 转 PDF", + "subtitle": "将 WPS Office 文档转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "WPS 文件", + "convertButton": "转换为 PDF" + }, + "xmlToPdf": { + "name": "XML 转 PDF", + "subtitle": "将 XML 文档转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "XML 文件", + "convertButton": "转换为 PDF" + }, + "pagesToPdf": { + "name": "Pages 转 PDF", + "subtitle": "将 Apple Pages 文档转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "Pages 文件", + "convertButton": "转换为 PDF" + }, + "odgToPdf": { + "name": "ODG 转 PDF", + "subtitle": "将 OpenDocument Graphics (ODG) 文件转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "ODG 文件", + "convertButton": "转换为 PDF" + }, + "odsToPdf": { + "name": "ODS 转 PDF", + "subtitle": "将 OpenDocument Spreadsheet (ODS) 文件转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "ODS 文件", + "convertButton": "转换为 PDF" + }, + "odpToPdf": { + "name": "ODP 转 PDF", + "subtitle": "将 OpenDocument Presentation (ODP) 文件转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "ODP 文件", + "convertButton": "转换为 PDF" + }, + "pubToPdf": { + "name": "PUB 转 PDF", + "subtitle": "将 Microsoft Publisher (PUB) 文件转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "PUB 文件", + "convertButton": "转换为 PDF" + }, + "vsdToPdf": { + "name": "VSD 转 PDF", + "subtitle": "将 Microsoft Visio (VSD, VSDX) 文件转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "VSD, VSDX 文件", + "convertButton": "转换为 PDF" + }, + "psdToPdf": { + "name": "PSD 转 PDF", + "subtitle": "将 Adobe Photoshop (PSD) 文件转换为 PDF 格式。支持多个文件。", + "acceptedFormats": "PSD 文件", + "convertButton": "转换为 PDF" + }, + "pdfToSvg": { + "name": "PDF 转 SVG", + "subtitle": "将 PDF 文件的每一页转换为可缩放矢量图形 (SVG),在任何尺寸下都能保持完美质量。" + }, + "extractTables": { + "name": "提取 PDF 表格", + "subtitle": "从 PDF 文件中提取表格,并导出为 CSV、JSON 或 Markdown 格式。" + }, + "pdfToCsv": { + "name": "PDF 转 CSV", + "subtitle": "从 PDF 中提取表格并转换为 CSV 格式。" + }, + "pdfToExcel": { + "name": "PDF 转 Excel", + "subtitle": "从 PDF 中提取表格并转换为 Excel (XLSX) 格式。" + }, + "pdfToText": { + "name": "PDF 转 文本", + "subtitle": "从 PDF 文件中提取文本并保存为纯文本文件 (.txt)。支持多个文件。", + "note": "此工具仅适用于数字创建的 PDF。对于扫描文档或基于图像的 PDF,请使用我们的 OCR PDF 工具。", + "convertButton": "提取文本" + }, + "digitalSignPdf": { + "name": "PDF 数字签名", + "pageTitle": "PDF 数字签名 - 添加加密签名 | BentoPDF", + "subtitle": "使用 X.509 证书为您的 PDF 添加加密数字签名。支持 PKCS#12 (.pfx, .p12) 和 PEM 格式。您的私钥永远不会离开您的浏览器。", + "certificateSection": "证书", + "uploadCert": "上传证书 (.pfx, .p12)", + "certPassword": "证书密码", + "certPasswordPlaceholder": "输入证书密码", + "certInfo": "证书信息", + "certSubject": "主体", + "certIssuer": "颁发者", + "certValidity": "有效期", + "signatureDetails": "签名详情(可选)", + "reason": "原因", + "reasonPlaceholder": "例如:我批准此文档", + "location": "位置", + "locationPlaceholder": "例如:北京,中国", + "contactInfo": "联系信息", + "contactPlaceholder": "例如:email@example.com", + "applySignature": "应用数字签名", + "successMessage": "PDF 签名成功!签名可在任何 PDF 阅读器中验证。" + }, + "validateSignaturePdf": { + "name": "验证 PDF 签名", + "pageTitle": "验证 PDF 签名 - 验证数字签名 | BentoPDF", + "subtitle": "验证您的 PDF 文件中的数字签名。检查证书有效性、查看签名者详情并确认文档完整性。所有处理都在您的浏览器中进行。" + }, + "emailToPdf": { + "name": "邮件转 PDF", + "subtitle": "将电子邮件文件 (EML, MSG) 转换为 PDF 格式。支持 Outlook 导出和标准邮件格式。", + "acceptedFormats": "EML, MSG 文件", + "convertButton": "转换为 PDF" + }, + "fontToOutline": { + "name": "字体转轮廓", + "subtitle": "将所有字体转换为矢量轮廓,确保在所有设备上一致呈现。" + }, + "deskewPdf": { + "name": "校正 PDF", + "subtitle": "使用 OpenCV 自动校正倾斜的扫描页面。" + } +} diff --git a/public/pdfjs-annotation-viewer/web/viewer.html b/public/pdfjs-annotation-viewer/web/viewer.html index d3a5a53..70d97ce 100644 --- a/public/pdfjs-annotation-viewer/web/viewer.html +++ b/public/pdfjs-annotation-viewer/web/viewer.html @@ -1,4 +1,4 @@ - + - - - + + + PDF.js viewer - - - + + + - + - - - + + +
-
-
- - - -
@@ -84,302 +133,895 @@ See https://github.com/adobe-type-tools/cmap-resources
-
-
-
- - - +
+ + +
-
+ +
+
+ - - ` - } else if (field.type === 'signature') { - specificProps = ` + `; + } else if (field.type === 'signature') { + specificProps = `
Signature fields are AcroForm signature fields and would only be visible in an advanced PDF viewer.
- ` - } else if (field.type === 'date') { - const formats = ['mm/dd/yyyy', 'dd/mm/yyyy', 'mm/yy', 'dd/mm/yy', 'yyyy/mm/dd', 'mmm d, yyyy', 'd-mmm-yy', 'yy-mm-dd'] - specificProps = ` + `; + } else if (field.type === 'date') { + const formats = [ + 'm/d', + 'm/d/yy', + 'm/d/yyyy', + 'mm/dd/yy', + 'mm/dd/yyyy', + 'mm/yy', + 'mm/yyyy', + 'd-mmm', + 'd-mmm-yy', + 'd-mmm-yyyy', + 'dd-mmm-yy', + 'dd-mmm-yyyy', + 'yy-mm-dd', + 'yyyy-mm-dd', + 'mmm-yy', + 'mmm-yyyy', + 'mmm d, yyyy', + 'mmmm-yy', + 'mmmm-yyyy', + 'mmmm d, yyyy', + 'dd/mm/yy', + 'dd/mm/yyyy', + 'yyyy/mm/dd', + 'dd.mm.yy', + 'dd.mm.yyyy', + 'm/d/yy h:MM tt', + 'm/d/yyyy h:MM tt', + 'm/d/yy HH:MM', + 'm/d/yyyy HH:MM', + 'yyyy-mm', + 'yyyy', + ]; + const isCustom = !formats.includes(field.dateFormat || 'mm/dd/yyyy'); + specificProps = `
-
- The selected format will be enforced when the user types or picks a date. +
+ + +
+
+ Example of current format: +
-

- - Browser Note: Firefox and Chrome may show their native date picker format during selection. The correct format will apply when you finish entering the date. This is normal browser behavior and not an issue. +

+ + Browser Note: Firefox and Chrome may show their native date picker format during selection. The correct format will apply when you finish entering the date.

- ` - } else if (field.type === 'image') { - specificProps = ` + `; + } else if (field.type === 'image') { + specificProps = `
@@ -930,27 +1113,47 @@ function showProperties(field: FormField): void {
Clicking this field in the PDF will open a file picker to upload an image.
- ` - } + `; + } - propertiesPanel.innerHTML = ` + propertiesPanel.innerHTML = `
- ${field.type === 'radio' && (existingRadioGroups.size > 0 || fields.some(f => f.type === 'radio' && f.id !== field.id)) ? ` + ${ + field.type === 'radio' && + (existingRadioGroups.size > 0 || + fields.some((f) => f.type === 'radio' && f.id !== field.id)) + ? `

Select to add this button to an existing group

- ` : ''} + ` + : '' + } ${specificProps}
@@ -976,1113 +1179,1337 @@ function showProperties(field: FormField): void { Delete Field
- ` + `; - // Common listeners - const propName = document.getElementById('propName') as HTMLInputElement - const nameError = document.getElementById('nameError') as HTMLDivElement - const propTooltip = document.getElementById('propTooltip') as HTMLInputElement - const propRequired = document.getElementById('propRequired') as HTMLInputElement - const propReadOnly = document.getElementById('propReadOnly') as HTMLInputElement - const deleteBtn = document.getElementById('deleteBtn') as HTMLButtonElement + // Common listeners + const propName = document.getElementById('propName') as HTMLInputElement; + const nameError = document.getElementById('nameError') as HTMLDivElement; + const propTooltip = document.getElementById( + 'propTooltip' + ) as HTMLInputElement; + const propRequired = document.getElementById( + 'propRequired' + ) as HTMLInputElement; + const propReadOnly = document.getElementById( + 'propReadOnly' + ) as HTMLInputElement; + const deleteBtn = document.getElementById('deleteBtn') as HTMLButtonElement; - const validateName = (newName: string): boolean => { - if (!newName) { - nameError.textContent = 'Field name cannot be empty' - nameError.classList.remove('hidden') - propName.classList.add('border-red-500') - return false - } - - if (field.type === 'radio') { - nameError.classList.add('hidden') - propName.classList.remove('border-red-500') - return true - } - - const isDuplicateInFields = fields.some(f => f.id !== field.id && f.name === newName) - const isDuplicateInPdf = existingFieldNames.has(newName) - - if (isDuplicateInFields || isDuplicateInPdf) { - nameError.textContent = `Field name "${newName}" already exists in this ${isDuplicateInPdf ? 'PDF' : 'form'}. Please try using a unique name.` - nameError.classList.remove('hidden') - propName.classList.add('border-red-500') - return false - } - - nameError.classList.add('hidden') - propName.classList.remove('border-red-500') - return true + const validateName = (newName: string): boolean => { + if (!newName) { + nameError.textContent = 'Field name cannot be empty'; + nameError.classList.remove('hidden'); + propName.classList.add('border-red-500'); + return false; } - propName.addEventListener('input', (e) => { - const newName = (e.target as HTMLInputElement).value.trim() - validateName(newName) - }) - - propName.addEventListener('change', (e) => { - const newName = (e.target as HTMLInputElement).value.trim() - - if (!validateName(newName)) { - (e.target as HTMLInputElement).value = field.name - return - } - - field.name = newName - const fieldWrapper = document.getElementById(field.id) - if (fieldWrapper) { - const label = fieldWrapper.querySelector('.field-label') as HTMLElement - if (label) label.textContent = field.name - } - }) - - propTooltip.addEventListener('input', (e) => { - field.tooltip = (e.target as HTMLInputElement).value - }) - if (field.type === 'radio') { - const existingGroupsSelect = document.getElementById('existingGroups') as HTMLSelectElement - if (existingGroupsSelect) { - existingGroupsSelect.addEventListener('change', (e) => { - const selectedGroup = (e.target as HTMLSelectElement).value - if (selectedGroup) { - propName.value = selectedGroup - field.name = selectedGroup - validateName(selectedGroup) - - // Update field label - const fieldWrapper = document.getElementById(field.id) - if (fieldWrapper) { - const label = fieldWrapper.querySelector('.field-label') as HTMLElement - if (label) label.textContent = field.name - } - } - }) - } + nameError.classList.add('hidden'); + propName.classList.remove('border-red-500'); + return true; } - propRequired.addEventListener('change', (e) => { - field.required = (e.target as HTMLInputElement).checked - }) + const isDuplicateInFields = fields.some( + (f) => f.id !== field.id && f.name === newName + ); + const isDuplicateInPdf = existingFieldNames.has(newName); - propReadOnly.addEventListener('change', (e) => { - field.readOnly = (e.target as HTMLInputElement).checked - }) - - const propBorderColor = document.getElementById('propBorderColor') as HTMLInputElement - const propHideBorder = document.getElementById('propHideBorder') as HTMLInputElement - - propBorderColor.addEventListener('input', (e) => { - field.borderColor = (e.target as HTMLInputElement).value - }) - - propHideBorder.addEventListener('change', (e) => { - field.hideBorder = (e.target as HTMLInputElement).checked - }) - - deleteBtn.addEventListener('click', () => { - deleteField(field) - }) - - // Specific listeners - if (field.type === 'text') { - const propValue = document.getElementById('propValue') as HTMLInputElement - const propMaxLength = document.getElementById('propMaxLength') as HTMLInputElement - const propComb = document.getElementById('propComb') as HTMLInputElement - const propFontSize = document.getElementById('propFontSize') as HTMLInputElement - const propTextColor = document.getElementById('propTextColor') as HTMLInputElement - const propAlignment = document.getElementById('propAlignment') as HTMLSelectElement - - propValue.addEventListener('input', (e) => { - field.defaultValue = (e.target as HTMLInputElement).value - const fieldWrapper = document.getElementById(field.id) - if (fieldWrapper) { - const textEl = fieldWrapper.querySelector('.field-text') as HTMLElement - if (textEl) textEl.textContent = field.defaultValue - } - }) - - propMaxLength.addEventListener('input', (e) => { - const val = parseInt((e.target as HTMLInputElement).value) - field.maxLength = isNaN(val) ? 0 : Math.max(0, val) - if (field.maxLength > 0) { - propValue.maxLength = field.maxLength - if (field.defaultValue.length > field.maxLength) { - field.defaultValue = field.defaultValue.substring(0, field.maxLength) - propValue.value = field.defaultValue - const fieldWrapper = document.getElementById(field.id) - if (fieldWrapper) { - const textEl = fieldWrapper.querySelector('.field-text') as HTMLElement - if (textEl) textEl.textContent = field.defaultValue - } - } - } else { - propValue.removeAttribute('maxLength') - } - }) - - propComb.addEventListener('input', (e) => { - const val = parseInt((e.target as HTMLInputElement).value) - field.combCells = isNaN(val) ? 0 : Math.max(0, val) - - if (field.combCells > 0) { - propValue.maxLength = field.combCells - propMaxLength.value = field.combCells.toString() - propMaxLength.disabled = true - field.maxLength = field.combCells - - if (field.defaultValue.length > field.combCells) { - field.defaultValue = field.defaultValue.substring(0, field.combCells) - propValue.value = field.defaultValue - } - } else { - propMaxLength.disabled = false - propValue.removeAttribute('maxLength') - if (field.maxLength > 0) { - propValue.maxLength = field.maxLength - } - } - - // Re-render field visual only, NOT the properties panel - const fieldWrapper = document.getElementById(field.id) - if (fieldWrapper) { - // Update text content - const textEl = fieldWrapper.querySelector('.field-text') as HTMLElement - if (textEl) { - textEl.textContent = field.defaultValue - if (field.combCells > 0) { - textEl.style.backgroundImage = `repeating-linear-gradient(90deg, transparent, transparent calc((100% / ${field.combCells}) - 1px), #e5e7eb calc((100% / ${field.combCells}) - 1px), #e5e7eb calc(100% / ${field.combCells}))` - textEl.style.fontFamily = 'monospace' - textEl.style.letterSpacing = `calc(${field.width / field.combCells}px - 1ch)` - textEl.style.paddingLeft = `calc((${field.width / field.combCells}px - 1ch) / 2)` - textEl.style.overflow = 'hidden' - textEl.style.textAlign = 'left' - textEl.style.justifyContent = 'flex-start' - } else { - textEl.style.backgroundImage = 'none' - textEl.style.fontFamily = 'inherit' - textEl.style.letterSpacing = 'normal' - textEl.style.textAlign = field.alignment - textEl.style.justifyContent = field.alignment === 'left' ? 'flex-start' : field.alignment === 'right' ? 'flex-end' : 'center' - } - } - } - }) - - propFontSize.addEventListener('input', (e) => { - field.fontSize = parseInt((e.target as HTMLInputElement).value) - const fieldWrapper = document.getElementById(field.id) - if (fieldWrapper) { - const textEl = fieldWrapper.querySelector('.field-text') as HTMLElement - if (textEl) textEl.style.fontSize = field.fontSize + 'px' - } - }) - - propTextColor.addEventListener('input', (e) => { - field.textColor = (e.target as HTMLInputElement).value - const fieldWrapper = document.getElementById(field.id) - if (fieldWrapper) { - const textEl = fieldWrapper.querySelector('.field-text') as HTMLElement - if (textEl) textEl.style.color = field.textColor - } - }) - - propAlignment.addEventListener('change', (e) => { - field.alignment = (e.target as HTMLSelectElement).value as 'left' | 'center' | 'right' - const fieldWrapper = document.getElementById(field.id) - if (fieldWrapper) { - const textEl = fieldWrapper.querySelector('.field-text') as HTMLElement - if (textEl) { - textEl.style.textAlign = field.alignment - textEl.style.justifyContent = field.alignment === 'left' ? 'flex-start' : field.alignment === 'right' ? 'flex-end' : 'center' - } - } - }) - - const propMultilineBtn = document.getElementById('propMultilineBtn') as HTMLButtonElement - if (propMultilineBtn) { - propMultilineBtn.addEventListener('click', () => { - field.multiline = !field.multiline - - // Update Toggle Button UI - const span = propMultilineBtn.querySelector('span') - if (field.multiline) { - propMultilineBtn.classList.remove('bg-gray-500') - propMultilineBtn.classList.add('bg-indigo-600') - span?.classList.remove('translate-x-0') - span?.classList.add('translate-x-6') - } else { - propMultilineBtn.classList.remove('bg-indigo-600') - propMultilineBtn.classList.add('bg-gray-500') - span?.classList.remove('translate-x-6') - span?.classList.add('translate-x-0') - } - - // Update Canvas UI - const fieldWrapper = document.getElementById(field.id) - if (fieldWrapper) { - const textEl = fieldWrapper.querySelector('.field-text') as HTMLElement - if (textEl) { - if (field.multiline) { - textEl.style.whiteSpace = 'pre-wrap' - textEl.style.alignItems = 'flex-start' - textEl.style.overflow = 'hidden' - } else { - textEl.style.whiteSpace = 'nowrap' - textEl.style.alignItems = 'center' - textEl.style.overflow = 'hidden' - } - } - } - }) - } - } else if (field.type === 'checkbox' || field.type === 'radio') { - const propCheckedBtn = document.getElementById('propCheckedBtn') as HTMLButtonElement - - propCheckedBtn.addEventListener('click', () => { - field.checked = !field.checked - - // Update Toggle Button UI - const span = propCheckedBtn.querySelector('span') - if (field.checked) { - propCheckedBtn.classList.remove('bg-gray-500') - propCheckedBtn.classList.add('bg-indigo-600') - span?.classList.remove('translate-x-0') - span?.classList.add('translate-x-6') - } else { - propCheckedBtn.classList.remove('bg-indigo-600') - propCheckedBtn.classList.add('bg-gray-500') - span?.classList.remove('translate-x-6') - span?.classList.add('translate-x-0') - } - - // Update Canvas UI - const fieldWrapper = document.getElementById(field.id) - if (fieldWrapper) { - const contentEl = fieldWrapper.querySelector('.field-content') as HTMLElement - if (contentEl) { - if (field.type === 'checkbox') { - contentEl.innerHTML = field.checked ? '' : '' - } else { - contentEl.innerHTML = field.checked ? '
' : '' - } - } - } - }) - - if (field.type === 'radio') { - const propGroupName = document.getElementById('propGroupName') as HTMLInputElement - const propExportValue = document.getElementById('propExportValue') as HTMLInputElement - - propGroupName.addEventListener('input', (e) => { - field.groupName = (e.target as HTMLInputElement).value - }) - propExportValue.addEventListener('input', (e) => { - field.exportValue = (e.target as HTMLInputElement).value - }) - } - } else if (field.type === 'dropdown' || field.type === 'optionlist') { - const propOptions = document.getElementById('propOptions') as HTMLTextAreaElement - propOptions.addEventListener('input', (e) => { - // We split by newline OR comma for the actual options array - const val = (e.target as HTMLTextAreaElement).value - field.options = val.split(/[\n,]/).map(s => s.trim()).filter(s => s.length > 0) - - const propSelectedOption = document.getElementById('propSelectedOption') as HTMLSelectElement - if (propSelectedOption) { - const currentVal = field.defaultValue - propSelectedOption.innerHTML = '' + - field.options?.map(opt => ``).join('') - - if (currentVal && field.options && !field.options.includes(currentVal)) { - field.defaultValue = '' - propSelectedOption.value = '' - } - } - - renderField(field) - }) - - const propSelectedOption = document.getElementById('propSelectedOption') as HTMLSelectElement - propSelectedOption.addEventListener('change', (e) => { - field.defaultValue = (e.target as HTMLSelectElement).value - - // Update visual on canvas - renderField(field) - }) - } else if (field.type === 'button') { - const propLabel = document.getElementById('propLabel') as HTMLInputElement - propLabel.addEventListener('input', (e) => { - field.label = (e.target as HTMLInputElement).value - const fieldWrapper = document.getElementById(field.id) - if (fieldWrapper) { - const contentEl = fieldWrapper.querySelector('.field-content') as HTMLElement - if (contentEl) contentEl.textContent = field.label || 'Button' - } - }) - - const propAction = document.getElementById('propAction') as HTMLSelectElement - const propUrlContainer = document.getElementById('propUrlContainer') as HTMLDivElement - const propJsContainer = document.getElementById('propJsContainer') as HTMLDivElement - const propShowHideContainer = document.getElementById('propShowHideContainer') as HTMLDivElement - - propAction.addEventListener('change', (e) => { - field.action = (e.target as HTMLSelectElement).value as any - - // Show/hide containers - propUrlContainer.classList.add('hidden') - propJsContainer.classList.add('hidden') - propShowHideContainer.classList.add('hidden') - - if (field.action === 'url') { - propUrlContainer.classList.remove('hidden') - } else if (field.action === 'js') { - propJsContainer.classList.remove('hidden') - } else if (field.action === 'showHide') { - propShowHideContainer.classList.remove('hidden') - } - }) - - const propActionUrl = document.getElementById('propActionUrl') as HTMLInputElement - propActionUrl.addEventListener('input', (e) => { - field.actionUrl = (e.target as HTMLInputElement).value - }) - - const propJsScript = document.getElementById('propJsScript') as HTMLTextAreaElement - if (propJsScript) { - propJsScript.addEventListener('input', (e) => { - field.jsScript = (e.target as HTMLTextAreaElement).value - }) - } - - const propTargetField = document.getElementById('propTargetField') as HTMLSelectElement - if (propTargetField) { - propTargetField.addEventListener('change', (e) => { - field.targetFieldName = (e.target as HTMLSelectElement).value - }) - } - - const propVisibilityAction = document.getElementById('propVisibilityAction') as HTMLSelectElement - if (propVisibilityAction) { - propVisibilityAction.addEventListener('change', (e) => { - field.visibilityAction = (e.target as HTMLSelectElement).value as any - }) - } - } else if (field.type === 'signature') { - // No specific listeners for signature fields yet - } else if (field.type === 'date') { - const propDateFormat = document.getElementById('propDateFormat') as HTMLSelectElement - if (propDateFormat) { - propDateFormat.addEventListener('change', (e) => { - field.dateFormat = (e.target as HTMLSelectElement).value - // Update canvas preview - const fieldWrapper = document.getElementById(field.id) - if (fieldWrapper) { - const textSpan = fieldWrapper.querySelector('.date-format-text') as HTMLElement - if (textSpan) { - textSpan.textContent = field.dateFormat - } - } - // Re-initialize lucide icons in the properties panel - setTimeout(() => (window as any).lucide?.createIcons(), 0) - }) - } - } else if (field.type === 'image') { - const propLabel = document.getElementById('propLabel') as HTMLInputElement - propLabel.addEventListener('input', (e) => { - field.label = (e.target as HTMLInputElement).value - renderField(field) - }) + if (isDuplicateInFields || isDuplicateInPdf) { + nameError.textContent = `Field name "${newName}" already exists in this ${isDuplicateInPdf ? 'PDF' : 'form'}. Please try using a unique name.`; + nameError.classList.remove('hidden'); + propName.classList.add('border-red-500'); + return false; } + + nameError.classList.add('hidden'); + propName.classList.remove('border-red-500'); + return true; + }; + + propName.addEventListener('input', (e) => { + const newName = (e.target as HTMLInputElement).value.trim(); + validateName(newName); + }); + + propName.addEventListener('change', (e) => { + const newName = (e.target as HTMLInputElement).value.trim(); + + if (!validateName(newName)) { + (e.target as HTMLInputElement).value = field.name; + return; + } + + field.name = newName; + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + const label = fieldWrapper.querySelector('.field-label') as HTMLElement; + if (label) label.textContent = field.name; + } + }); + + propTooltip.addEventListener('input', (e) => { + field.tooltip = (e.target as HTMLInputElement).value; + }); + + if (field.type === 'radio') { + const existingGroupsSelect = document.getElementById( + 'existingGroups' + ) as HTMLSelectElement; + if (existingGroupsSelect) { + existingGroupsSelect.addEventListener('change', (e) => { + const selectedGroup = (e.target as HTMLSelectElement).value; + if (selectedGroup) { + propName.value = selectedGroup; + field.name = selectedGroup; + validateName(selectedGroup); + + // Update field label + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + const label = fieldWrapper.querySelector( + '.field-label' + ) as HTMLElement; + if (label) label.textContent = field.name; + } + } + }); + } + } + + propRequired.addEventListener('change', (e) => { + field.required = (e.target as HTMLInputElement).checked; + }); + + propReadOnly.addEventListener('change', (e) => { + field.readOnly = (e.target as HTMLInputElement).checked; + }); + + const propBorderColor = document.getElementById( + 'propBorderColor' + ) as HTMLInputElement; + const propHideBorder = document.getElementById( + 'propHideBorder' + ) as HTMLInputElement; + + propBorderColor.addEventListener('input', (e) => { + field.borderColor = (e.target as HTMLInputElement).value; + }); + + propHideBorder.addEventListener('change', (e) => { + field.hideBorder = (e.target as HTMLInputElement).checked; + }); + + deleteBtn.addEventListener('click', () => { + deleteField(field); + }); + + // Specific listeners + if (field.type === 'text') { + const propValue = document.getElementById('propValue') as HTMLInputElement; + const propMaxLength = document.getElementById( + 'propMaxLength' + ) as HTMLInputElement; + const propComb = document.getElementById('propComb') as HTMLInputElement; + const propFontSize = document.getElementById( + 'propFontSize' + ) as HTMLInputElement; + const propTextColor = document.getElementById( + 'propTextColor' + ) as HTMLInputElement; + const propAlignment = document.getElementById( + 'propAlignment' + ) as HTMLSelectElement; + + propValue.addEventListener('input', (e) => { + field.defaultValue = (e.target as HTMLInputElement).value; + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + const textEl = fieldWrapper.querySelector('.field-text') as HTMLElement; + if (textEl) textEl.textContent = field.defaultValue; + } + }); + + propMaxLength.addEventListener('input', (e) => { + const val = parseInt((e.target as HTMLInputElement).value); + field.maxLength = isNaN(val) ? 0 : Math.max(0, val); + if (field.maxLength > 0) { + propValue.maxLength = field.maxLength; + if (field.defaultValue.length > field.maxLength) { + field.defaultValue = field.defaultValue.substring(0, field.maxLength); + propValue.value = field.defaultValue; + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + const textEl = fieldWrapper.querySelector( + '.field-text' + ) as HTMLElement; + if (textEl) textEl.textContent = field.defaultValue; + } + } + } else { + propValue.removeAttribute('maxLength'); + } + }); + + propComb.addEventListener('input', (e) => { + const val = parseInt((e.target as HTMLInputElement).value); + field.combCells = isNaN(val) ? 0 : Math.max(0, val); + + if (field.combCells > 0) { + propValue.maxLength = field.combCells; + propMaxLength.value = field.combCells.toString(); + propMaxLength.disabled = true; + field.maxLength = field.combCells; + + if (field.defaultValue.length > field.combCells) { + field.defaultValue = field.defaultValue.substring(0, field.combCells); + propValue.value = field.defaultValue; + } + } else { + propMaxLength.disabled = false; + propValue.removeAttribute('maxLength'); + if (field.maxLength > 0) { + propValue.maxLength = field.maxLength; + } + } + + // Re-render field visual only, NOT the properties panel + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + // Update text content + const textEl = fieldWrapper.querySelector('.field-text') as HTMLElement; + if (textEl) { + textEl.textContent = field.defaultValue; + if (field.combCells > 0) { + textEl.style.backgroundImage = `repeating-linear-gradient(90deg, transparent, transparent calc((100% / ${field.combCells}) - 1px), #e5e7eb calc((100% / ${field.combCells}) - 1px), #e5e7eb calc(100% / ${field.combCells}))`; + textEl.style.fontFamily = 'monospace'; + textEl.style.letterSpacing = `calc(${field.width / field.combCells}px - 1ch)`; + textEl.style.paddingLeft = `calc((${field.width / field.combCells}px - 1ch) / 2)`; + textEl.style.overflow = 'hidden'; + textEl.style.textAlign = 'left'; + textEl.style.justifyContent = 'flex-start'; + } else { + textEl.style.backgroundImage = 'none'; + textEl.style.fontFamily = 'inherit'; + textEl.style.letterSpacing = 'normal'; + textEl.style.textAlign = field.alignment; + textEl.style.justifyContent = + field.alignment === 'left' + ? 'flex-start' + : field.alignment === 'right' + ? 'flex-end' + : 'center'; + } + } + } + }); + + propFontSize.addEventListener('input', (e) => { + field.fontSize = parseInt((e.target as HTMLInputElement).value); + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + const textEl = fieldWrapper.querySelector('.field-text') as HTMLElement; + if (textEl) textEl.style.fontSize = field.fontSize + 'px'; + } + }); + + propTextColor.addEventListener('input', (e) => { + field.textColor = (e.target as HTMLInputElement).value; + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + const textEl = fieldWrapper.querySelector('.field-text') as HTMLElement; + if (textEl) textEl.style.color = field.textColor; + } + }); + + propAlignment.addEventListener('change', (e) => { + field.alignment = (e.target as HTMLSelectElement).value as + | 'left' + | 'center' + | 'right'; + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + const textEl = fieldWrapper.querySelector('.field-text') as HTMLElement; + if (textEl) { + textEl.style.textAlign = field.alignment; + textEl.style.justifyContent = + field.alignment === 'left' + ? 'flex-start' + : field.alignment === 'right' + ? 'flex-end' + : 'center'; + } + } + }); + + const propMultilineBtn = document.getElementById( + 'propMultilineBtn' + ) as HTMLButtonElement; + if (propMultilineBtn) { + propMultilineBtn.addEventListener('click', () => { + field.multiline = !field.multiline; + + // Update Toggle Button UI + const span = propMultilineBtn.querySelector('span'); + if (field.multiline) { + propMultilineBtn.classList.remove('bg-gray-500'); + propMultilineBtn.classList.add('bg-indigo-600'); + span?.classList.remove('translate-x-0'); + span?.classList.add('translate-x-6'); + } else { + propMultilineBtn.classList.remove('bg-indigo-600'); + propMultilineBtn.classList.add('bg-gray-500'); + span?.classList.remove('translate-x-6'); + span?.classList.add('translate-x-0'); + } + + // Update Canvas UI + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + const textEl = fieldWrapper.querySelector( + '.field-text' + ) as HTMLElement; + if (textEl) { + if (field.multiline) { + textEl.style.whiteSpace = 'pre-wrap'; + textEl.style.alignItems = 'flex-start'; + textEl.style.overflow = 'hidden'; + } else { + textEl.style.whiteSpace = 'nowrap'; + textEl.style.alignItems = 'center'; + textEl.style.overflow = 'hidden'; + } + } + } + }); + } + } else if (field.type === 'checkbox' || field.type === 'radio') { + const propCheckedBtn = document.getElementById( + 'propCheckedBtn' + ) as HTMLButtonElement; + + propCheckedBtn.addEventListener('click', () => { + field.checked = !field.checked; + + // Update Toggle Button UI + const span = propCheckedBtn.querySelector('span'); + if (field.checked) { + propCheckedBtn.classList.remove('bg-gray-500'); + propCheckedBtn.classList.add('bg-indigo-600'); + span?.classList.remove('translate-x-0'); + span?.classList.add('translate-x-6'); + } else { + propCheckedBtn.classList.remove('bg-indigo-600'); + propCheckedBtn.classList.add('bg-gray-500'); + span?.classList.remove('translate-x-6'); + span?.classList.add('translate-x-0'); + } + + // Update Canvas UI + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + const contentEl = fieldWrapper.querySelector( + '.field-content' + ) as HTMLElement; + if (contentEl) { + if (field.type === 'checkbox') { + contentEl.innerHTML = field.checked + ? '' + : ''; + } else { + contentEl.innerHTML = field.checked + ? '
' + : ''; + } + } + } + }); + + if (field.type === 'radio') { + const propGroupName = document.getElementById( + 'propGroupName' + ) as HTMLInputElement; + const propExportValue = document.getElementById( + 'propExportValue' + ) as HTMLInputElement; + + propGroupName.addEventListener('input', (e) => { + field.groupName = (e.target as HTMLInputElement).value; + }); + propExportValue.addEventListener('input', (e) => { + field.exportValue = (e.target as HTMLInputElement).value; + }); + } + } else if (field.type === 'dropdown' || field.type === 'optionlist') { + const propOptions = document.getElementById( + 'propOptions' + ) as HTMLTextAreaElement; + propOptions.addEventListener('input', (e) => { + // We split by newline OR comma for the actual options array + const val = (e.target as HTMLTextAreaElement).value; + field.options = val + .split(/[\n,]/) + .map((s) => s.trim()) + .filter((s) => s.length > 0); + + const propSelectedOption = document.getElementById( + 'propSelectedOption' + ) as HTMLSelectElement; + if (propSelectedOption) { + const currentVal = field.defaultValue; + propSelectedOption.innerHTML = + '' + + field.options + ?.map( + (opt) => + `` + ) + .join(''); + + if ( + currentVal && + field.options && + !field.options.includes(currentVal) + ) { + field.defaultValue = ''; + propSelectedOption.value = ''; + } + } + + renderField(field); + }); + + const propSelectedOption = document.getElementById( + 'propSelectedOption' + ) as HTMLSelectElement; + propSelectedOption.addEventListener('change', (e) => { + field.defaultValue = (e.target as HTMLSelectElement).value; + + // Update visual on canvas + renderField(field); + }); + } else if (field.type === 'button') { + const propLabel = document.getElementById('propLabel') as HTMLInputElement; + propLabel.addEventListener('input', (e) => { + field.label = (e.target as HTMLInputElement).value; + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + const contentEl = fieldWrapper.querySelector( + '.field-content' + ) as HTMLElement; + if (contentEl) contentEl.textContent = field.label || 'Button'; + } + }); + + const propAction = document.getElementById( + 'propAction' + ) as HTMLSelectElement; + const propUrlContainer = document.getElementById( + 'propUrlContainer' + ) as HTMLDivElement; + const propJsContainer = document.getElementById( + 'propJsContainer' + ) as HTMLDivElement; + const propShowHideContainer = document.getElementById( + 'propShowHideContainer' + ) as HTMLDivElement; + + propAction.addEventListener('change', (e) => { + field.action = (e.target as HTMLSelectElement).value as any; + + // Show/hide containers + propUrlContainer.classList.add('hidden'); + propJsContainer.classList.add('hidden'); + propShowHideContainer.classList.add('hidden'); + + if (field.action === 'url') { + propUrlContainer.classList.remove('hidden'); + } else if (field.action === 'js') { + propJsContainer.classList.remove('hidden'); + } else if (field.action === 'showHide') { + propShowHideContainer.classList.remove('hidden'); + } + }); + + const propActionUrl = document.getElementById( + 'propActionUrl' + ) as HTMLInputElement; + propActionUrl.addEventListener('input', (e) => { + field.actionUrl = (e.target as HTMLInputElement).value; + }); + + const propJsScript = document.getElementById( + 'propJsScript' + ) as HTMLTextAreaElement; + if (propJsScript) { + propJsScript.addEventListener('input', (e) => { + field.jsScript = (e.target as HTMLTextAreaElement).value; + }); + } + + const propTargetField = document.getElementById( + 'propTargetField' + ) as HTMLSelectElement; + if (propTargetField) { + propTargetField.addEventListener('change', (e) => { + field.targetFieldName = (e.target as HTMLSelectElement).value; + }); + } + + const propVisibilityAction = document.getElementById( + 'propVisibilityAction' + ) as HTMLSelectElement; + if (propVisibilityAction) { + propVisibilityAction.addEventListener('change', (e) => { + field.visibilityAction = (e.target as HTMLSelectElement).value as any; + }); + } + } else if (field.type === 'signature') { + // No specific listeners for signature fields yet + } else if (field.type === 'date') { + const propDateFormat = document.getElementById( + 'propDateFormat' + ) as HTMLSelectElement; + const customFormatContainer = document.getElementById( + 'customFormatContainer' + ) as HTMLDivElement; + const propCustomFormat = document.getElementById( + 'propCustomFormat' + ) as HTMLInputElement; + const dateFormatExample = document.getElementById( + 'dateFormatExample' + ) as HTMLSpanElement; + + const formatDateExample = (format: string): string => { + const now = new Date(); + const d = now.getDate(); + const dd = d.toString().padStart(2, '0'); + const m = now.getMonth() + 1; + const mm = m.toString().padStart(2, '0'); + const yy = now.getFullYear().toString().slice(-2); + const yyyy = now.getFullYear().toString(); + const h = now.getHours() % 12 || 12; + const HH = now.getHours().toString().padStart(2, '0'); + const MM = now.getMinutes().toString().padStart(2, '0'); + const tt = now.getHours() >= 12 ? 'PM' : 'AM'; + const monthNames = [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'May', + 'Jun', + 'Jul', + 'Aug', + 'Sep', + 'Oct', + 'Nov', + 'Dec', + ]; + const monthNamesFull = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', + ]; + const mmm = monthNames[now.getMonth()]; + const mmmm = monthNamesFull[now.getMonth()]; + + return format + .replace(/mmmm/g, mmmm) + .replace(/mmm/g, mmm) + .replace(/mm/g, mm) + .replace(/m/g, m.toString()) + .replace(/dddd/g, dd) + .replace(/dd/g, dd) + .replace(/d/g, d.toString()) + .replace(/yyyy/g, yyyy) + .replace(/yy/g, yy) + .replace(/HH/g, HH) + .replace(/h/g, h.toString()) + .replace(/MM/g, MM) + .replace(/tt/g, tt); + }; + + const updateExample = () => { + if (dateFormatExample) { + dateFormatExample.textContent = formatDateExample( + field.dateFormat || 'mm/dd/yyyy' + ); + } + }; + + updateExample(); + + if (propDateFormat) { + propDateFormat.addEventListener('change', (e) => { + const value = (e.target as HTMLSelectElement).value; + if (value === 'custom') { + customFormatContainer?.classList.remove('hidden'); + if (propCustomFormat && propCustomFormat.value) { + field.dateFormat = propCustomFormat.value; + } + } else { + customFormatContainer?.classList.add('hidden'); + field.dateFormat = value; + } + updateExample(); + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + const textSpan = fieldWrapper.querySelector( + '.date-format-text' + ) as HTMLElement; + if (textSpan) { + textSpan.textContent = field.dateFormat; + } + } + setTimeout(() => (window as any).lucide?.createIcons(), 0); + }); + } + + if (propCustomFormat) { + propCustomFormat.addEventListener('input', (e) => { + field.dateFormat = (e.target as HTMLInputElement).value || 'mm/dd/yyyy'; + updateExample(); + const fieldWrapper = document.getElementById(field.id); + if (fieldWrapper) { + const textSpan = fieldWrapper.querySelector( + '.date-format-text' + ) as HTMLElement; + if (textSpan) { + textSpan.textContent = field.dateFormat; + } + } + }); + } + } else if (field.type === 'image') { + const propLabel = document.getElementById('propLabel') as HTMLInputElement; + propLabel.addEventListener('input', (e) => { + field.label = (e.target as HTMLInputElement).value; + renderField(field); + }); + } } // Hide properties panel function hideProperties(): void { - propertiesPanel.innerHTML = '

Select a field to edit properties

' + propertiesPanel.innerHTML = + '

Select a field to edit properties

'; } // Delete field function deleteField(field: FormField): void { - const fieldEl = document.getElementById(field.id) - if (fieldEl) { - fieldEl.remove() - } - fields = fields.filter((f) => f.id !== field.id) - deselectAll() - updateFieldCount() + const fieldEl = document.getElementById(field.id); + if (fieldEl) { + fieldEl.remove(); + } + fields = fields.filter((f) => f.id !== field.id); + deselectAll(); + updateFieldCount(); } // Delete key handler document.addEventListener('keydown', (e) => { - if (e.key === 'Delete' && selectedField) { - deleteField(selectedField) - } else if (e.key === 'Escape' && selectedToolType) { - // Cancel tool selection - toolItems.forEach(item => item.classList.remove('ring-2', 'ring-indigo-400', 'bg-indigo-600')) - selectedToolType = null - canvas.style.cursor = 'default' - } -}) + if (e.key === 'Delete' && selectedField) { + deleteField(selectedField); + } else if (e.key === 'Escape' && selectedToolType) { + // Cancel tool selection + toolItems.forEach((item) => + item.classList.remove('ring-2', 'ring-indigo-400', 'bg-indigo-600') + ); + selectedToolType = null; + canvas.style.cursor = 'default'; + } +}); // Update field count function updateFieldCount(): void { - fieldCountDisplay.textContent = fields.length.toString() + fieldCountDisplay.textContent = fields.length.toString(); } // Download PDF downloadBtn.addEventListener('click', async () => { - // Check for duplicate field names before generating PDF - const nameCount = new Map() - const duplicates: string[] = [] - const conflictsWithPdf: string[] = [] + // Check for duplicate field names before generating PDF + const nameCount = new Map(); + const duplicates: string[] = []; + const conflictsWithPdf: string[] = []; - fields.forEach(field => { - const count = nameCount.get(field.name) || 0 - nameCount.set(field.name, count + 1) + fields.forEach((field) => { + const count = nameCount.get(field.name) || 0; + nameCount.set(field.name, count + 1); - if (existingFieldNames.has(field.name)) { - if (field.type === 'radio' && existingRadioGroups.has(field.name)) { - } else { - conflictsWithPdf.push(field.name) - } - } - }) + if (existingFieldNames.has(field.name)) { + if (field.type === 'radio' && existingRadioGroups.has(field.name)) { + } else { + conflictsWithPdf.push(field.name); + } + } + }); - nameCount.forEach((count, name) => { - if (count > 1) { - const fieldsWithName = fields.filter(f => f.name === name) - const allRadio = fieldsWithName.every(f => f.type === 'radio') + nameCount.forEach((count, name) => { + if (count > 1) { + const fieldsWithName = fields.filter((f) => f.name === name); + const allRadio = fieldsWithName.every((f) => f.type === 'radio'); - if (!allRadio) { - duplicates.push(name) - } - } - }) + if (!allRadio) { + duplicates.push(name); + } + } + }); - if (conflictsWithPdf.length > 0) { - const conflictList = [...new Set(conflictsWithPdf)].map(name => `"${name}"`).join(', ') - showModal( - 'Field Name Conflict', - `The following field names already exist in the uploaded PDF: ${conflictList}. Please rename these fields before downloading.`, - 'error' - ) - return + if (conflictsWithPdf.length > 0) { + const conflictList = [...new Set(conflictsWithPdf)] + .map((name) => `"${name}"`) + .join(', '); + showModal( + 'Field Name Conflict', + `The following field names already exist in the uploaded PDF: ${conflictList}. Please rename these fields before downloading.`, + 'error' + ); + return; + } + + if (duplicates.length > 0) { + const duplicateList = duplicates.map((name) => `"${name}"`).join(', '); + showModal( + 'Duplicate Field Names', + `The following field names are used more than once: ${duplicateList}. Please rename these fields to use unique names before downloading.`, + 'error' + ); + return; + } + + if (fields.length === 0) { + alert('Please add at least one field before downloading.'); + return; + } + + if (pages.length === 0) { + alert('No pages found. Please create a blank PDF or upload one.'); + return; + } + + try { + let pdfDoc: PDFDocument; + + if (uploadedPdfDoc) { + pdfDoc = uploadedPdfDoc; + } else { + pdfDoc = await PDFDocument.create(); + + for (const pageData of pages) { + pdfDoc.addPage([pageData.width, pageData.height]); + } } - if (duplicates.length > 0) { - const duplicateList = duplicates.map(name => `"${name}"`).join(', ') - showModal( - 'Duplicate Field Names', - `The following field names are used more than once: ${duplicateList}. Please rename these fields to use unique names before downloading.`, - 'error' - ) - return - } + const form = pdfDoc.getForm(); - if (fields.length === 0) { - alert('Please add at least one field before downloading.') - return - } + const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica); - if (pages.length === 0) { - alert('No pages found. Please create a blank PDF or upload one.') - return - } + // Set document metadata for accessibility + pdfDoc.setTitle('Fillable Form'); + pdfDoc.setAuthor('BentoPDF'); + pdfDoc.setLanguage('en-US'); - try { - let pdfDoc: PDFDocument + const radioGroups = new Map(); // Track created radio groups - if (uploadedPdfDoc) { - pdfDoc = uploadedPdfDoc + for (const field of fields) { + const pageData = pages[field.pageIndex]; + if (!pageData) continue; + + const pdfPage = pdfDoc.getPage(field.pageIndex); + const { height: pageHeight } = pdfPage.getSize(); + + const scaleX = 1 / pdfViewerScale; + const scaleY = 1 / pdfViewerScale; + + const adjustedX = field.x - pdfViewerOffset.x; + const adjustedY = field.y - pdfViewerOffset.y; + + const x = adjustedX * scaleX; + const y = pageHeight - adjustedY * scaleY - field.height * scaleY; + const width = field.width * scaleX; + const height = field.height * scaleY; + + console.log(`Field "${field.name}":`, { + screenPos: { x: field.x, y: field.y }, + adjustedPos: { x: adjustedX, y: adjustedY }, + pdfPos: { x, y, width, height }, + metrics: { offset: pdfViewerOffset, scale: pdfViewerScale }, + }); + + if (field.type === 'text') { + const textField = form.createTextField(field.name); + const rgbColor = hexToRgb(field.textColor); + const borderRgb = hexToRgb(field.borderColor || '#000000'); + + textField.addToPage(pdfPage, { + x: x, + y: y, + width: width, + height: height, + borderWidth: field.hideBorder ? 0 : 1, + borderColor: rgb(borderRgb.r, borderRgb.g, borderRgb.b), + backgroundColor: rgb(1, 1, 1), + textColor: rgb(rgbColor.r, rgbColor.g, rgbColor.b), + }); + + textField.setText(field.defaultValue); + textField.setFontSize(field.fontSize); + + // Set alignment + if (field.alignment === 'center') { + textField.setAlignment(TextAlignment.Center); + } else if (field.alignment === 'right') { + textField.setAlignment(TextAlignment.Right); } else { - pdfDoc = await PDFDocument.create() - - for (const pageData of pages) { - pdfDoc.addPage([pageData.width, pageData.height]) - } + textField.setAlignment(TextAlignment.Left); } - const form = pdfDoc.getForm() - - const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica) - - // Set document metadata for accessibility - pdfDoc.setTitle('Fillable Form') - pdfDoc.setAuthor('BentoPDF') - pdfDoc.setLanguage('en-US') - - const radioGroups = new Map() // Track created radio groups - - for (const field of fields) { - const pageData = pages[field.pageIndex] - if (!pageData) continue - - const pdfPage = pdfDoc.getPage(field.pageIndex) - const { height: pageHeight } = pdfPage.getSize() - - const scaleX = 1 / pdfViewerScale - const scaleY = 1 / pdfViewerScale - - const adjustedX = field.x - pdfViewerOffset.x - const adjustedY = field.y - pdfViewerOffset.y - - const x = adjustedX * scaleX - const y = pageHeight - (adjustedY * scaleY) - (field.height * scaleY) - const width = field.width * scaleX - const height = field.height * scaleY - - console.log(`Field "${field.name}":`, { - screenPos: { x: field.x, y: field.y }, - adjustedPos: { x: adjustedX, y: adjustedY }, - pdfPos: { x, y, width, height }, - metrics: { offset: pdfViewerOffset, scale: pdfViewerScale } - }) - - if (field.type === 'text') { - const textField = form.createTextField(field.name) - const rgbColor = hexToRgb(field.textColor) - const borderRgb = hexToRgb(field.borderColor || '#000000') - - textField.addToPage(pdfPage, { - x: x, - y: y, - width: width, - height: height, - borderWidth: field.hideBorder ? 0 : 1, - borderColor: rgb(borderRgb.r, borderRgb.g, borderRgb.b), - backgroundColor: rgb(1, 1, 1), - textColor: rgb(rgbColor.r, rgbColor.g, rgbColor.b), - }) - - textField.setText(field.defaultValue) - textField.setFontSize(field.fontSize) - - // Set alignment - if (field.alignment === 'center') { - textField.setAlignment(TextAlignment.Center) - } else if (field.alignment === 'right') { - textField.setAlignment(TextAlignment.Right) - } else { - textField.setAlignment(TextAlignment.Left) - } - - // Handle combing - if (field.combCells > 0) { - textField.setMaxLength(field.combCells) - textField.enableCombing() - } else if (field.maxLength > 0) { - textField.setMaxLength(field.maxLength) - } - - // Disable multiline to prevent RTL issues (unless explicitly enabled) - if (!field.multiline) { - textField.disableMultiline() - } else { - textField.enableMultiline() - } - - // Common properties - if (field.required) textField.enableRequired() - if (field.readOnly) textField.enableReadOnly() - if (field.tooltip) { - textField.acroField.getWidgets().forEach(widget => { - widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)) - }) - } - - } else if (field.type === 'checkbox') { - const checkBox = form.createCheckBox(field.name) - const borderRgb = hexToRgb(field.borderColor || '#000000') - checkBox.addToPage(pdfPage, { - x: x, - y: y, - width: width, - height: height, - borderWidth: field.hideBorder ? 0 : 1, - borderColor: rgb(borderRgb.r, borderRgb.g, borderRgb.b), - backgroundColor: rgb(1, 1, 1), - }) - if (field.checked) checkBox.check() - if (field.required) checkBox.enableRequired() - if (field.readOnly) checkBox.enableReadOnly() - if (field.tooltip) { - checkBox.acroField.getWidgets().forEach(widget => { - widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)) - }) - } - - } else if (field.type === 'radio') { - const groupName = field.name - let radioGroup - - if (radioGroups.has(groupName)) { - radioGroup = radioGroups.get(groupName) - } else { - const existingField = form.getFieldMaybe(groupName) - - if (existingField) { - radioGroup = existingField - radioGroups.set(groupName, radioGroup) - console.log(`Using existing radio group from PDF: ${groupName}`) - } else { - radioGroup = form.createRadioGroup(groupName) - radioGroups.set(groupName, radioGroup) - console.log(`Created new radio group: ${groupName}`) - } - } - - const borderRgb = hexToRgb(field.borderColor || '#000000') - radioGroup.addOptionToPage(field.exportValue || 'Yes', pdfPage as any, { - x: x, - y: y, - width: width, - height: height, - borderWidth: field.hideBorder ? 0 : 1, - borderColor: rgb(borderRgb.r, borderRgb.g, borderRgb.b), - backgroundColor: rgb(1, 1, 1), - }) - if (field.checked) radioGroup.select(field.exportValue || 'Yes') - if (field.required) radioGroup.enableRequired() - if (field.readOnly) radioGroup.enableReadOnly() - if (field.tooltip) { - radioGroup.acroField.getWidgets().forEach((widget: any) => { - widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)) - }) - } - - } else if (field.type === 'dropdown') { - const dropdown = form.createDropdown(field.name) - const borderRgb = hexToRgb(field.borderColor || '#000000') - dropdown.addToPage(pdfPage, { - x: x, - y: y, - width: width, - height: height, - borderWidth: field.hideBorder ? 0 : 1, - borderColor: rgb(borderRgb.r, borderRgb.g, borderRgb.b), - backgroundColor: rgb(1, 1, 1), // Light blue not supported in standard PDF appearance easily without streams - }) - if (field.options) dropdown.setOptions(field.options) - if (field.defaultValue && field.options?.includes(field.defaultValue)) dropdown.select(field.defaultValue) - else if (field.options && field.options.length > 0) dropdown.select(field.options[0]) - - const rgbColor = hexToRgb(field.textColor) - dropdown.acroField.setFontSize(field.fontSize) - dropdown.acroField.setDefaultAppearance( - `0 0 0 rg /Helv ${field.fontSize} Tf` - ) - - if (field.required) dropdown.enableRequired() - if (field.readOnly) dropdown.enableReadOnly() - if (field.tooltip) { - dropdown.acroField.getWidgets().forEach(widget => { - widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)) - }) - } - - } else if (field.type === 'optionlist') { - const optionList = form.createOptionList(field.name) - const borderRgb = hexToRgb(field.borderColor || '#000000') - optionList.addToPage(pdfPage, { - x: x, - y: y, - width: width, - height: height, - borderWidth: field.hideBorder ? 0 : 1, - borderColor: rgb(borderRgb.r, borderRgb.g, borderRgb.b), - backgroundColor: rgb(1, 1, 1), - }) - if (field.options) optionList.setOptions(field.options) - if (field.defaultValue && field.options?.includes(field.defaultValue)) optionList.select(field.defaultValue) - else if (field.options && field.options.length > 0) optionList.select(field.options[0]) - - const rgbColor = hexToRgb(field.textColor) - optionList.acroField.setFontSize(field.fontSize) - optionList.acroField.setDefaultAppearance( - `0 0 0 rg /Helv ${field.fontSize} Tf` - ) - - if (field.required) optionList.enableRequired() - if (field.readOnly) optionList.enableReadOnly() - if (field.tooltip) { - optionList.acroField.getWidgets().forEach(widget => { - widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)) - }) - } - - } else if (field.type === 'button') { - const button = form.createButton(field.name) - const borderRgb = hexToRgb(field.borderColor || '#000000') - button.addToPage(field.label || 'Button', pdfPage, { - x: x, - y: y, - width: width, - height: height, - borderWidth: field.hideBorder ? 0 : 1, - borderColor: rgb(borderRgb.r, borderRgb.g, borderRgb.b), - backgroundColor: rgb(0.8, 0.8, 0.8), // Light gray - }) - - // Add Action - if (field.action && field.action !== 'none') { - const widgets = button.acroField.getWidgets() - - widgets.forEach(widget => { - let actionDict: any - - if (field.action === 'reset') { - actionDict = pdfDoc.context.obj({ - Type: 'Action', - S: 'ResetForm' - }) - } else if (field.action === 'print') { - // Print action using JavaScript - actionDict = pdfDoc.context.obj({ - Type: 'Action', - S: 'JavaScript', - JS: 'print();' - }) - } else if (field.action === 'url' && field.actionUrl) { - // Validate URL - let url = field.actionUrl.trim() - if (!url.startsWith('http://') && !url.startsWith('https://')) { - url = 'https://' + url - } - - // Encode URL to handle special characters (RFC3986) - try { - url = encodeURI(url) - } catch (e) { - console.warn('Failed to encode URL:', e) - } - - actionDict = pdfDoc.context.obj({ - Type: 'Action', - S: 'URI', - URI: PDFString.of(url) - }) - } else if (field.action === 'js' && field.jsScript) { - actionDict = pdfDoc.context.obj({ - Type: 'Action', - S: 'JavaScript', - JS: field.jsScript - }) - } else if (field.action === 'showHide' && field.targetFieldName) { - const target = field.targetFieldName - let script = '' - - if (field.visibilityAction === 'show') { - script = `var f = this.getField("${target}"); if(f) f.display = display.visible;` - } else if (field.visibilityAction === 'hide') { - script = `var f = this.getField("${target}"); if(f) f.display = display.hidden;` - } else { - // Toggle - script = `var f = this.getField("${target}"); if(f) f.display = (f.display === display.visible) ? display.hidden : display.visible;` - } - - actionDict = pdfDoc.context.obj({ - Type: 'Action', - S: 'JavaScript', - JS: script - }) - } - - if (actionDict) { - widget.dict.set(PDFName.of('A'), actionDict) - } - }) - } - - if (field.tooltip) { - button.acroField.getWidgets().forEach(widget => { - widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)) - }) - } - } else if (field.type === 'date') { - const dateField = form.createTextField(field.name) - dateField.addToPage(pdfPage, { - x: x, - y: y, - width: width, - height: height, - borderWidth: 1, - borderColor: rgb(0, 0, 0), - backgroundColor: rgb(1, 1, 1), - }) - - // Add Date Format and Keystroke Actions to the FIELD (not widget) - const dateFormat = field.dateFormat || 'mm/dd/yyyy' - - const formatAction = pdfDoc.context.obj({ - Type: 'Action', - S: 'JavaScript', - JS: PDFString.of(`AFDate_FormatEx("${dateFormat}");`) - }) - - const keystrokeAction = pdfDoc.context.obj({ - Type: 'Action', - S: 'JavaScript', - JS: PDFString.of(`AFDate_KeystrokeEx("${dateFormat}");`) - }) - - // Attach AA (Additional Actions) to the field dictionary - const additionalActions = pdfDoc.context.obj({ - F: formatAction, - K: keystrokeAction - }) - dateField.acroField.dict.set(PDFName.of('AA'), additionalActions) - - if (field.required) dateField.enableRequired() - if (field.readOnly) dateField.enableReadOnly() - if (field.tooltip) { - dateField.acroField.getWidgets().forEach(widget => { - widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)) - }) - } - } else if (field.type === 'image') { - const imageBtn = form.createButton(field.name) - imageBtn.addToPage(field.label || 'Click to Upload Image', pdfPage, { - x: x, - y: y, - width: width, - height: height, - borderWidth: 1, - borderColor: rgb(0, 0, 0), - backgroundColor: rgb(0.9, 0.9, 0.9), - }) - - // Add Import Icon Action - const widgets = imageBtn.acroField.getWidgets() - widgets.forEach(widget => { - const actionDict = pdfDoc.context.obj({ - Type: 'Action', - S: 'JavaScript', - JS: 'event.target.buttonImportIcon();' - }) - widget.dict.set(PDFName.of('A'), actionDict) - - // Set Appearance Characteristics (MK) -> Text Position (TP) = 1 (Icon Only) - // This ensures the image replaces the text when uploaded - // IF (Icon Fit) -> SW: A (Always Scale), S: A (Anamorphic/Fill) - const mkDict = pdfDoc.context.obj({ - TP: 1, - BG: [0.9, 0.9, 0.9], // Background color (Light Gray) - BC: [0, 0, 0], // Border color (Black) - IF: { - SW: PDFName.of('A'), - S: PDFName.of('A'), - FB: true - } - }) - widget.dict.set(PDFName.of('MK'), mkDict) - }) - - if (field.tooltip) { - imageBtn.acroField.getWidgets().forEach(widget => { - widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)) - }) - } - } else if (field.type === 'signature') { - const context = pdfDoc.context - - // Create the signature field dictionary with FT = Sig - const sigDict = context.obj({ - FT: PDFName.of('Sig'), - T: PDFString.of(field.name), - Kids: [], - }) as PDFDict - const sigRef = context.register(sigDict) - - // Create the widget annotation for the signature field - const widgetDict = context.obj({ - Type: PDFName.of('Annot'), - Subtype: PDFName.of('Widget'), - Rect: [x, y, x + width, y + height], - F: 4, // Print flag - P: pdfPage.ref, - Parent: sigRef, - }) as PDFDict - - // Add border and background appearance - const borderStyle = context.obj({ - W: 1, // Border width - S: PDFName.of('S'), // Solid border - }) as PDFDict - widgetDict.set(PDFName.of('BS'), borderStyle) - widgetDict.set(PDFName.of('BC'), context.obj([0, 0, 0])) // Border color (black) - widgetDict.set(PDFName.of('BG'), context.obj([0.95, 0.95, 0.95])) // Background color - - const widgetRef = context.register(widgetDict) - - const kidsArray = sigDict.get(PDFName.of('Kids')) as PDFArray - kidsArray.push(widgetRef) - - pdfPage.node.addAnnot(widgetRef) - - const acroForm = form.acroForm - acroForm.addField(sigRef) - - // Add tooltip if specified - if (field.tooltip) { - widgetDict.set(PDFName.of('TU'), PDFString.of(field.tooltip)) - } - } + // Handle combing + if (field.combCells > 0) { + textField.setMaxLength(field.combCells); + textField.enableCombing(); + } else if (field.maxLength > 0) { + textField.setMaxLength(field.maxLength); } - form.updateFieldAppearances(helveticaFont) - - const pdfBytes = await pdfDoc.save() - const blob = new Blob([new Uint8Array(pdfBytes)], { type: 'application/pdf' }) - downloadFile(blob, 'fillable-form.pdf') - showModal('Success', 'Your PDF has been downloaded successfully.', 'info', () => { - resetToInitial() - }, 'Okay') - } catch (error) { - console.error('Error generating PDF:', error) - const errorMessage = (error as Error).message - - // Check if it's a duplicate field name error - if (errorMessage.includes('A field already exists with the specified name')) { - // Extract the field name from the error message - const match = errorMessage.match(/A field already exists with the specified name: "(.+?)"/) - const fieldName = match ? match[1] : 'unknown' - - if (existingRadioGroups.has(fieldName)) { - console.log(`Adding to existing radio group: ${fieldName}`) - } else { - showModal('Duplicate Field Name', `A field named "${fieldName}" already exists. Please rename this field to use a unique name before downloading.`, 'error') - } + // Disable multiline to prevent RTL issues (unless explicitly enabled) + if (!field.multiline) { + textField.disableMultiline(); } else { - showModal('Error', 'Error generating PDF: ' + errorMessage, 'error') + textField.enableMultiline(); } + + // Common properties + if (field.required) textField.enableRequired(); + if (field.readOnly) textField.enableReadOnly(); + if (field.tooltip) { + textField.acroField.getWidgets().forEach((widget) => { + widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)); + }); + } + } else if (field.type === 'checkbox') { + const checkBox = form.createCheckBox(field.name); + const borderRgb = hexToRgb(field.borderColor || '#000000'); + checkBox.addToPage(pdfPage, { + x: x, + y: y, + width: width, + height: height, + borderWidth: field.hideBorder ? 0 : 1, + borderColor: rgb(borderRgb.r, borderRgb.g, borderRgb.b), + backgroundColor: rgb(1, 1, 1), + }); + if (field.checked) checkBox.check(); + if (field.required) checkBox.enableRequired(); + if (field.readOnly) checkBox.enableReadOnly(); + if (field.tooltip) { + checkBox.acroField.getWidgets().forEach((widget) => { + widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)); + }); + } + } else if (field.type === 'radio') { + const groupName = field.name; + let radioGroup; + + if (radioGroups.has(groupName)) { + radioGroup = radioGroups.get(groupName); + } else { + const existingField = form.getFieldMaybe(groupName); + + if (existingField) { + radioGroup = existingField; + radioGroups.set(groupName, radioGroup); + console.log(`Using existing radio group from PDF: ${groupName}`); + } else { + radioGroup = form.createRadioGroup(groupName); + radioGroups.set(groupName, radioGroup); + console.log(`Created new radio group: ${groupName}`); + } + } + + const borderRgb = hexToRgb(field.borderColor || '#000000'); + radioGroup.addOptionToPage(field.exportValue || 'Yes', pdfPage as any, { + x: x, + y: y, + width: width, + height: height, + borderWidth: field.hideBorder ? 0 : 1, + borderColor: rgb(borderRgb.r, borderRgb.g, borderRgb.b), + backgroundColor: rgb(1, 1, 1), + }); + if (field.checked) radioGroup.select(field.exportValue || 'Yes'); + if (field.required) radioGroup.enableRequired(); + if (field.readOnly) radioGroup.enableReadOnly(); + if (field.tooltip) { + radioGroup.acroField.getWidgets().forEach((widget: any) => { + widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)); + }); + } + } else if (field.type === 'dropdown') { + const dropdown = form.createDropdown(field.name); + const borderRgb = hexToRgb(field.borderColor || '#000000'); + dropdown.addToPage(pdfPage, { + x: x, + y: y, + width: width, + height: height, + borderWidth: field.hideBorder ? 0 : 1, + borderColor: rgb(borderRgb.r, borderRgb.g, borderRgb.b), + backgroundColor: rgb(1, 1, 1), // Light blue not supported in standard PDF appearance easily without streams + }); + if (field.options) dropdown.setOptions(field.options); + if (field.defaultValue && field.options?.includes(field.defaultValue)) + dropdown.select(field.defaultValue); + else if (field.options && field.options.length > 0) + dropdown.select(field.options[0]); + + const rgbColor = hexToRgb(field.textColor); + dropdown.acroField.setFontSize(field.fontSize); + dropdown.acroField.setDefaultAppearance( + `0 0 0 rg /Helv ${field.fontSize} Tf` + ); + + if (field.required) dropdown.enableRequired(); + if (field.readOnly) dropdown.enableReadOnly(); + if (field.tooltip) { + dropdown.acroField.getWidgets().forEach((widget) => { + widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)); + }); + } + } else if (field.type === 'optionlist') { + const optionList = form.createOptionList(field.name); + const borderRgb = hexToRgb(field.borderColor || '#000000'); + optionList.addToPage(pdfPage, { + x: x, + y: y, + width: width, + height: height, + borderWidth: field.hideBorder ? 0 : 1, + borderColor: rgb(borderRgb.r, borderRgb.g, borderRgb.b), + backgroundColor: rgb(1, 1, 1), + }); + if (field.options) optionList.setOptions(field.options); + if (field.defaultValue && field.options?.includes(field.defaultValue)) + optionList.select(field.defaultValue); + else if (field.options && field.options.length > 0) + optionList.select(field.options[0]); + + const rgbColor = hexToRgb(field.textColor); + optionList.acroField.setFontSize(field.fontSize); + optionList.acroField.setDefaultAppearance( + `0 0 0 rg /Helv ${field.fontSize} Tf` + ); + + if (field.required) optionList.enableRequired(); + if (field.readOnly) optionList.enableReadOnly(); + if (field.tooltip) { + optionList.acroField.getWidgets().forEach((widget) => { + widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)); + }); + } + } else if (field.type === 'button') { + const button = form.createButton(field.name); + const borderRgb = hexToRgb(field.borderColor || '#000000'); + button.addToPage(field.label || 'Button', pdfPage, { + x: x, + y: y, + width: width, + height: height, + borderWidth: field.hideBorder ? 0 : 1, + borderColor: rgb(borderRgb.r, borderRgb.g, borderRgb.b), + backgroundColor: rgb(0.8, 0.8, 0.8), // Light gray + }); + + // Add Action + if (field.action && field.action !== 'none') { + const widgets = button.acroField.getWidgets(); + + widgets.forEach((widget) => { + let actionDict: any; + + if (field.action === 'reset') { + actionDict = pdfDoc.context.obj({ + Type: 'Action', + S: 'ResetForm', + }); + } else if (field.action === 'print') { + // Print action using JavaScript + actionDict = pdfDoc.context.obj({ + Type: 'Action', + S: 'JavaScript', + JS: 'print();', + }); + } else if (field.action === 'url' && field.actionUrl) { + // Validate URL + let url = field.actionUrl.trim(); + if (!url.startsWith('http://') && !url.startsWith('https://')) { + url = 'https://' + url; + } + + // Encode URL to handle special characters (RFC3986) + try { + url = encodeURI(url); + } catch (e) { + console.warn('Failed to encode URL:', e); + } + + actionDict = pdfDoc.context.obj({ + Type: 'Action', + S: 'URI', + URI: PDFString.of(url), + }); + } else if (field.action === 'js' && field.jsScript) { + actionDict = pdfDoc.context.obj({ + Type: 'Action', + S: 'JavaScript', + JS: field.jsScript, + }); + } else if (field.action === 'showHide' && field.targetFieldName) { + const target = field.targetFieldName; + let script = ''; + + if (field.visibilityAction === 'show') { + script = `var f = this.getField("${target}"); if(f) f.display = display.visible;`; + } else if (field.visibilityAction === 'hide') { + script = `var f = this.getField("${target}"); if(f) f.display = display.hidden;`; + } else { + // Toggle + script = `var f = this.getField("${target}"); if(f) f.display = (f.display === display.visible) ? display.hidden : display.visible;`; + } + + actionDict = pdfDoc.context.obj({ + Type: 'Action', + S: 'JavaScript', + JS: script, + }); + } + + if (actionDict) { + widget.dict.set(PDFName.of('A'), actionDict); + } + }); + } + + if (field.tooltip) { + button.acroField.getWidgets().forEach((widget) => { + widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)); + }); + } + } else if (field.type === 'date') { + const dateField = form.createTextField(field.name); + dateField.addToPage(pdfPage, { + x: x, + y: y, + width: width, + height: height, + borderWidth: 1, + borderColor: rgb(0, 0, 0), + backgroundColor: rgb(1, 1, 1), + }); + + // Add Date Format and Keystroke Actions to the FIELD (not widget) + const dateFormat = field.dateFormat || 'mm/dd/yyyy'; + + const formatAction = pdfDoc.context.obj({ + Type: 'Action', + S: 'JavaScript', + JS: PDFString.of(`AFDate_FormatEx("${dateFormat}");`), + }); + + const keystrokeAction = pdfDoc.context.obj({ + Type: 'Action', + S: 'JavaScript', + JS: PDFString.of(`AFDate_KeystrokeEx("${dateFormat}");`), + }); + + // Attach AA (Additional Actions) to the field dictionary + const additionalActions = pdfDoc.context.obj({ + F: formatAction, + K: keystrokeAction, + }); + dateField.acroField.dict.set(PDFName.of('AA'), additionalActions); + + if (field.required) dateField.enableRequired(); + if (field.readOnly) dateField.enableReadOnly(); + if (field.tooltip) { + dateField.acroField.getWidgets().forEach((widget) => { + widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)); + }); + } + } else if (field.type === 'image') { + const imageBtn = form.createButton(field.name); + imageBtn.addToPage(field.label || 'Click to Upload Image', pdfPage, { + x: x, + y: y, + width: width, + height: height, + borderWidth: 1, + borderColor: rgb(0, 0, 0), + backgroundColor: rgb(0.9, 0.9, 0.9), + }); + + // Add Import Icon Action + const widgets = imageBtn.acroField.getWidgets(); + widgets.forEach((widget) => { + const actionDict = pdfDoc.context.obj({ + Type: 'Action', + S: 'JavaScript', + JS: 'event.target.buttonImportIcon();', + }); + widget.dict.set(PDFName.of('A'), actionDict); + + // Set Appearance Characteristics (MK) -> Text Position (TP) = 1 (Icon Only) + // This ensures the image replaces the text when uploaded + // IF (Icon Fit) -> SW: A (Always Scale), S: A (Anamorphic/Fill) + const mkDict = pdfDoc.context.obj({ + TP: 1, + BG: [0.9, 0.9, 0.9], // Background color (Light Gray) + BC: [0, 0, 0], // Border color (Black) + IF: { + SW: PDFName.of('A'), + S: PDFName.of('A'), + FB: true, + }, + }); + widget.dict.set(PDFName.of('MK'), mkDict); + }); + + if (field.tooltip) { + imageBtn.acroField.getWidgets().forEach((widget) => { + widget.dict.set(PDFName.of('TU'), PDFString.of(field.tooltip)); + }); + } + } else if (field.type === 'signature') { + const context = pdfDoc.context; + + // Create the signature field dictionary with FT = Sig + const sigDict = context.obj({ + FT: PDFName.of('Sig'), + T: PDFString.of(field.name), + Kids: [], + }) as PDFDict; + const sigRef = context.register(sigDict); + + // Create the widget annotation for the signature field + const widgetDict = context.obj({ + Type: PDFName.of('Annot'), + Subtype: PDFName.of('Widget'), + Rect: [x, y, x + width, y + height], + F: 4, // Print flag + P: pdfPage.ref, + Parent: sigRef, + }) as PDFDict; + + // Add border and background appearance + const borderStyle = context.obj({ + W: 1, // Border width + S: PDFName.of('S'), // Solid border + }) as PDFDict; + widgetDict.set(PDFName.of('BS'), borderStyle); + widgetDict.set(PDFName.of('BC'), context.obj([0, 0, 0])); // Border color (black) + widgetDict.set(PDFName.of('BG'), context.obj([0.95, 0.95, 0.95])); // Background color + + const widgetRef = context.register(widgetDict); + + const kidsArray = sigDict.get(PDFName.of('Kids')) as PDFArray; + kidsArray.push(widgetRef); + + pdfPage.node.addAnnot(widgetRef); + + const acroForm = form.acroForm; + acroForm.addField(sigRef); + + // Add tooltip if specified + if (field.tooltip) { + widgetDict.set(PDFName.of('TU'), PDFString.of(field.tooltip)); + } + } } -}) + + form.updateFieldAppearances(helveticaFont); + + const pdfBytes = await pdfDoc.save(); + const blob = new Blob([new Uint8Array(pdfBytes)], { + type: 'application/pdf', + }); + downloadFile(blob, 'fillable-form.pdf'); + showModal( + 'Success', + 'Your PDF has been downloaded successfully.', + 'info', + () => { + resetToInitial(); + }, + 'Okay' + ); + } catch (error) { + console.error('Error generating PDF:', error); + const errorMessage = (error as Error).message; + + // Check if it's a duplicate field name error + if ( + errorMessage.includes('A field already exists with the specified name') + ) { + // Extract the field name from the error message + const match = errorMessage.match( + /A field already exists with the specified name: "(.+?)"/ + ); + const fieldName = match ? match[1] : 'unknown'; + + if (existingRadioGroups.has(fieldName)) { + console.log(`Adding to existing radio group: ${fieldName}`); + } else { + showModal( + 'Duplicate Field Name', + `A field named "${fieldName}" already exists. Please rename this field to use a unique name before downloading.`, + 'error' + ); + } + } else { + showModal('Error', 'Error generating PDF: ' + errorMessage, 'error'); + } + } +}); // Back to tools button -const backToToolsBtns = document.querySelectorAll('[id^="back-to-tools"]') as NodeListOf -backToToolsBtns.forEach(btn => { - btn.addEventListener('click', () => { - window.location.href = import.meta.env.BASE_URL - }) -}) +const backToToolsBtns = document.querySelectorAll( + '[id^="back-to-tools"]' +) as NodeListOf; +backToToolsBtns.forEach((btn) => { + btn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); +}); function getPageDimensions(size: string): { width: number; height: number } { - let dimensions: [number, number] - switch (size) { - case 'letter': - dimensions = PageSizes.Letter - break - case 'a4': - dimensions = PageSizes.A4 - break - case 'a5': - dimensions = PageSizes.A5 - break - case 'legal': - dimensions = PageSizes.Legal - break - case 'tabloid': - dimensions = PageSizes.Tabloid - break - case 'a3': - dimensions = PageSizes.A3 - break - case 'custom': - // Get custom dimensions from inputs - const width = parseInt(customWidth.value) || 612 - const height = parseInt(customHeight.value) || 792 - return { width, height } - default: - dimensions = PageSizes.Letter - } - return { width: dimensions[0], height: dimensions[1] } + let dimensions: [number, number]; + switch (size) { + case 'letter': + dimensions = PageSizes.Letter; + break; + case 'a4': + dimensions = PageSizes.A4; + break; + case 'a5': + dimensions = PageSizes.A5; + break; + case 'legal': + dimensions = PageSizes.Legal; + break; + case 'tabloid': + dimensions = PageSizes.Tabloid; + break; + case 'a3': + dimensions = PageSizes.A3; + break; + case 'custom': + // Get custom dimensions from inputs + const width = parseInt(customWidth.value) || 612; + const height = parseInt(customHeight.value) || 792; + return { width, height }; + default: + dimensions = PageSizes.Letter; + } + return { width: dimensions[0], height: dimensions[1] }; } // Reset to initial state function resetToInitial(): void { - fields = [] - pages = [] - currentPageIndex = 0 - uploadedPdfDoc = null - selectedField = null + fields = []; + pages = []; + currentPageIndex = 0; + uploadedPdfDoc = null; + selectedField = null; - canvas.innerHTML = '' + canvas.innerHTML = ''; - propertiesPanel.innerHTML = '

Select a field to edit properties

' + propertiesPanel.innerHTML = + '

Select a field to edit properties

'; - updateFieldCount() + updateFieldCount(); - // Show upload area and hide tool container - uploadArea.classList.remove('hidden') - toolContainer.classList.add('hidden') - pageSizeSelector.classList.add('hidden') - setTimeout(() => createIcons({ icons }), 100) + // Show upload area and hide tool container + uploadArea.classList.remove('hidden'); + toolContainer.classList.add('hidden'); + pageSizeSelector.classList.add('hidden'); + setTimeout(() => createIcons({ icons }), 100); } function createBlankPage(): void { - pages.push({ - index: pages.length, - width: pageSize.width, - height: pageSize.height - }) - updatePageNavigation() + pages.push({ + index: pages.length, + width: pageSize.width, + height: pageSize.height, + }); + updatePageNavigation(); } function switchToPage(pageIndex: number): void { - if (pageIndex < 0 || pageIndex >= pages.length) return + if (pageIndex < 0 || pageIndex >= pages.length) return; - currentPageIndex = pageIndex - renderCanvas() - updatePageNavigation() + currentPageIndex = pageIndex; + renderCanvas(); + updatePageNavigation(); - // Deselect any selected field when switching pages - deselectAll() + // Deselect any selected field when switching pages + deselectAll(); } // Render the canvas for the current page async function renderCanvas(): Promise { - const currentPage = pages[currentPageIndex] - if (!currentPage) return + const currentPage = pages[currentPageIndex]; + if (!currentPage) return; - // Fixed scale for better visibility - let scale = 1.333 + // Fixed scale for better visibility + const scale = 1.333; - currentScale = scale + currentScale = scale; - // Use actual PDF page dimensions (not scaled) - const canvasWidth = currentPage.width * scale - const canvasHeight = currentPage.height * scale + // Use actual PDF page dimensions (not scaled) + const canvasWidth = currentPage.width * scale; + const canvasHeight = currentPage.height * scale; - canvas.style.width = `${canvasWidth}px` - canvas.style.height = `${canvasHeight}px` + canvas.style.width = `${canvasWidth}px`; + canvas.style.height = `${canvasHeight}px`; - canvas.innerHTML = '' + canvas.innerHTML = ''; - if (uploadedPdfDoc) { + if (uploadedPdfDoc) { + try { + const arrayBuffer = await uploadedPdfDoc.save(); + const blob = new Blob([arrayBuffer.buffer as ArrayBuffer], { + type: 'application/pdf', + }); + const blobUrl = URL.createObjectURL(blob); + + const iframe = document.createElement('iframe'); + iframe.src = `${import.meta.env.BASE_URL}pdfjs-viewer/viewer.html?file=${encodeURIComponent(blobUrl)}#page=${currentPageIndex + 1}&toolbar=0`; + iframe.style.width = '100%'; + iframe.style.height = `${canvasHeight}px`; + iframe.style.border = 'none'; + iframe.style.position = 'absolute'; + iframe.style.top = '0'; + iframe.style.left = '0'; + iframe.style.pointerEvents = 'none'; + iframe.style.opacity = '0.8'; + + iframe.onload = () => { try { - const arrayBuffer = await uploadedPdfDoc.save() - const blob = new Blob([arrayBuffer.buffer as ArrayBuffer], { type: 'application/pdf' }) - const blobUrl = URL.createObjectURL(blob) + const viewerWindow = iframe.contentWindow as any; + if (viewerWindow && viewerWindow.PDFViewerApplication) { + const app = viewerWindow.PDFViewerApplication; - const iframe = document.createElement('iframe') - iframe.src = `${import.meta.env.BASE_URL}pdfjs-viewer/viewer.html?file=${encodeURIComponent(blobUrl)}#page=${currentPageIndex + 1}&toolbar=0` - iframe.style.width = '100%' - iframe.style.height = `${canvasHeight}px` - iframe.style.border = 'none' - iframe.style.position = 'absolute' - iframe.style.top = '0' - iframe.style.left = '0' - iframe.style.pointerEvents = 'none' - iframe.style.opacity = '0.8' - - iframe.onload = () => { - try { - const viewerWindow = iframe.contentWindow as any - if (viewerWindow && viewerWindow.PDFViewerApplication) { - const app = viewerWindow.PDFViewerApplication - - const style = viewerWindow.document.createElement('style') - style.textContent = ` + const style = viewerWindow.document.createElement('style'); + style.textContent = ` * { margin: 0 !important; padding: 0 !important; @@ -2128,268 +2555,306 @@ async function renderCanvas(): Promise { border: none !important; box-shadow: none !important; } - ` - viewerWindow.document.head.appendChild(style) + `; + viewerWindow.document.head.appendChild(style); - const checkRender = setInterval(() => { - if (app.pdfViewer && app.pdfViewer.pagesCount > 0) { - clearInterval(checkRender) + const checkRender = setInterval(() => { + if (app.pdfViewer && app.pdfViewer.pagesCount > 0) { + clearInterval(checkRender); - const pageContainer = viewerWindow.document.querySelector('.page') - if (pageContainer) { - const initialRect = pageContainer.getBoundingClientRect() + const pageContainer = + viewerWindow.document.querySelector('.page'); + if (pageContainer) { + const initialRect = pageContainer.getBoundingClientRect(); - const offsetX = -initialRect.left - const offsetY = -initialRect.top - pageContainer.style.transform = `translate(${offsetX}px, ${offsetY}px)` + const offsetX = -initialRect.left; + const offsetY = -initialRect.top; + pageContainer.style.transform = `translate(${offsetX}px, ${offsetY}px)`; - setTimeout(() => { - const rect = pageContainer.getBoundingClientRect() - const style = viewerWindow.getComputedStyle(pageContainer) + setTimeout(() => { + const rect = pageContainer.getBoundingClientRect(); + const style = viewerWindow.getComputedStyle(pageContainer); - const borderLeft = parseFloat(style.borderLeftWidth) || 0 - const borderTop = parseFloat(style.borderTopWidth) || 0 - const borderRight = parseFloat(style.borderRightWidth) || 0 + const borderLeft = parseFloat(style.borderLeftWidth) || 0; + const borderTop = parseFloat(style.borderTopWidth) || 0; + const borderRight = parseFloat(style.borderRightWidth) || 0; - pdfViewerOffset = { - x: rect.left + borderLeft, - y: rect.top + borderTop - } + pdfViewerOffset = { + x: rect.left + borderLeft, + y: rect.top + borderTop, + }; - const contentWidth = rect.width - borderLeft - borderRight - pdfViewerScale = contentWidth / currentPage.width + const contentWidth = rect.width - borderLeft - borderRight; + pdfViewerScale = contentWidth / currentPage.width; - console.log('📏 Calibrated Metrics (force positioned):', { - initialPosition: { left: initialRect.left, top: initialRect.top }, - appliedTransform: { x: offsetX, y: offsetY }, - finalRect: { left: rect.left, top: rect.top, width: rect.width, height: rect.height }, - computedBorders: { left: borderLeft, top: borderTop, right: borderRight }, - finalOffset: pdfViewerOffset, - finalScale: pdfViewerScale, - pdfDimensions: { width: currentPage.width, height: currentPage.height } - }) - }, 50) - } - } - }, 100) - } - } catch (e) { - console.error('Error accessing iframe content:', e) + console.log('📏 Calibrated Metrics (force positioned):', { + initialPosition: { + left: initialRect.left, + top: initialRect.top, + }, + appliedTransform: { x: offsetX, y: offsetY }, + finalRect: { + left: rect.left, + top: rect.top, + width: rect.width, + height: rect.height, + }, + computedBorders: { + left: borderLeft, + top: borderTop, + right: borderRight, + }, + finalOffset: pdfViewerOffset, + finalScale: pdfViewerScale, + pdfDimensions: { + width: currentPage.width, + height: currentPage.height, + }, + }); + }, 50); } - } - - canvas.appendChild(iframe) - - console.log('Canvas dimensions:', { width: canvasWidth, height: canvasHeight, scale: currentScale }) - console.log('PDF page dimensions:', { width: currentPage.width, height: currentPage.height }) - } catch (error) { - console.error('Error rendering PDF:', error) + } + }, 100); + } + } catch (e) { + console.error('Error accessing iframe content:', e); } - } + }; - fields.filter(f => f.pageIndex === currentPageIndex).forEach(field => { - renderField(field) - }) + canvas.appendChild(iframe); + + console.log('Canvas dimensions:', { + width: canvasWidth, + height: canvasHeight, + scale: currentScale, + }); + console.log('PDF page dimensions:', { + width: currentPage.width, + height: currentPage.height, + }); + } catch (error) { + console.error('Error rendering PDF:', error); + } + } + + fields + .filter((f) => f.pageIndex === currentPageIndex) + .forEach((field) => { + renderField(field); + }); } function updatePageNavigation(): void { - pageIndicator.textContent = `Page ${currentPageIndex + 1} of ${pages.length}` - prevPageBtn.disabled = currentPageIndex === 0 - nextPageBtn.disabled = currentPageIndex === pages.length - 1 + pageIndicator.textContent = `Page ${currentPageIndex + 1} of ${pages.length}`; + prevPageBtn.disabled = currentPageIndex === 0; + nextPageBtn.disabled = currentPageIndex === pages.length - 1; } // Drag and drop handlers for upload area dropZone.addEventListener('dragover', (e) => { - e.preventDefault() - dropZone.classList.add('border-indigo-500', 'bg-gray-600') -}) + e.preventDefault(); + dropZone.classList.add('border-indigo-500', 'bg-gray-600'); +}); dropZone.addEventListener('dragleave', () => { - dropZone.classList.remove('border-indigo-500', 'bg-gray-600') -}) + dropZone.classList.remove('border-indigo-500', 'bg-gray-600'); +}); dropZone.addEventListener('drop', (e) => { - e.preventDefault() - dropZone.classList.remove('border-indigo-500', 'bg-gray-600') - const files = e.dataTransfer?.files - if (files && files.length > 0 && files[0].type === 'application/pdf') { - handlePdfUpload(files[0]) - } -}) + e.preventDefault(); + dropZone.classList.remove('border-indigo-500', 'bg-gray-600'); + const files = e.dataTransfer?.files; + if (files && files.length > 0 && files[0].type === 'application/pdf') { + handlePdfUpload(files[0]); + } +}); pdfFileInput.addEventListener('change', async (e) => { - const file = (e.target as HTMLInputElement).files?.[0] - if (file) { - handlePdfUpload(file) - } -}) + const file = (e.target as HTMLInputElement).files?.[0]; + if (file) { + handlePdfUpload(file); + } +}); blankPdfBtn.addEventListener('click', () => { - pageSizeSelector.classList.remove('hidden') -}) + pageSizeSelector.classList.remove('hidden'); +}); pageSizeSelect.addEventListener('change', () => { - if (pageSizeSelect.value === 'custom') { - customDimensionsInput.classList.remove('hidden') - } else { - customDimensionsInput.classList.add('hidden') - } -}) + if (pageSizeSelect.value === 'custom') { + customDimensionsInput.classList.remove('hidden'); + } else { + customDimensionsInput.classList.add('hidden'); + } +}); confirmBlankBtn.addEventListener('click', () => { - const selectedSize = pageSizeSelect.value - pageSize = getPageDimensions(selectedSize) + const selectedSize = pageSizeSelect.value; + pageSize = getPageDimensions(selectedSize); - createBlankPage() - switchToPage(0) + createBlankPage(); + switchToPage(0); - // Hide upload area and show tool container - uploadArea.classList.add('hidden') - toolContainer.classList.remove('hidden') - setTimeout(() => createIcons({ icons }), 100) -}) + // Hide upload area and show tool container + uploadArea.classList.add('hidden'); + toolContainer.classList.remove('hidden'); + setTimeout(() => createIcons({ icons }), 100); +}); async function handlePdfUpload(file: File) { + try { + const arrayBuffer = await file.arrayBuffer(); + uploadedPdfDoc = await PDFDocument.load(arrayBuffer); + + // Check for existing fields and update counter + existingFieldNames.clear(); try { - const arrayBuffer = await file.arrayBuffer() - uploadedPdfDoc = await PDFDocument.load(arrayBuffer) + const form = uploadedPdfDoc.getForm(); + const pdfFields = form.getFields(); - // Check for existing fields and update counter - existingFieldNames.clear() - try { - const form = uploadedPdfDoc.getForm() - const pdfFields = form.getFields() + // console.log('📋 Found', pdfFields.length, 'existing fields in uploaded PDF') - // console.log('📋 Found', pdfFields.length, 'existing fields in uploaded PDF') + pdfFields.forEach((field) => { + const name = field.getName(); + existingFieldNames.add(name); // Track all existing field names - pdfFields.forEach(field => { - const name = field.getName() - existingFieldNames.add(name) // Track all existing field names - - if (field instanceof PDFRadioGroup) { - existingRadioGroups.add(name) - } - - // console.log(' Field:', name, '| Type:', field.constructor.name) - - const match = name.match(/([a-zA-Z]+)_(\d+)/) - if (match) { - const num = parseInt(match[2]) - if (!isNaN(num) && num > fieldCounter) { - fieldCounter = num - console.log(' → Updated field counter to:', fieldCounter) - } - } - }) - - // TODO@ALAM: DEBUGGER - // console.log('Field counter after upload:', fieldCounter) - // console.log('Existing field names:', Array.from(existingFieldNames)) - } catch (e) { - console.log('No form fields found or error reading fields:', e) + if (field instanceof PDFRadioGroup) { + existingRadioGroups.add(name); } - uploadedPdfjsDoc = await getPDFDocument({ data: arrayBuffer }).promise + // console.log(' Field:', name, '| Type:', field.constructor.name) - const pageCount = uploadedPdfDoc.getPageCount() - pages = [] - - for (let i = 0; i < pageCount; i++) { - const page = uploadedPdfDoc.getPage(i) - const { width, height } = page.getSize() - - pages.push({ - index: i, - width, - height, - pdfPageData: undefined - }) + const match = name.match(/([a-zA-Z]+)_(\d+)/); + if (match) { + const num = parseInt(match[2]); + if (!isNaN(num) && num > fieldCounter) { + fieldCounter = num; + console.log(' → Updated field counter to:', fieldCounter); + } } + }); - currentPageIndex = 0 - renderCanvas() - updatePageNavigation() - - // Hide upload area and show tool container - uploadArea.classList.add('hidden') - toolContainer.classList.remove('hidden') - - // Init icons - setTimeout(() => createIcons({ icons }), 100) - } catch (error) { - console.error('Error loading PDF:', error) - showModal('Error', 'Error loading PDF file. Please try again with a valid PDF.', 'error') + // TODO@ALAM: DEBUGGER + // console.log('Field counter after upload:', fieldCounter) + // console.log('Existing field names:', Array.from(existingFieldNames)) + } catch (e) { + console.log('No form fields found or error reading fields:', e); } + + uploadedPdfjsDoc = await getPDFDocument({ data: arrayBuffer }).promise; + + const pageCount = uploadedPdfDoc.getPageCount(); + pages = []; + + for (let i = 0; i < pageCount; i++) { + const page = uploadedPdfDoc.getPage(i); + const { width, height } = page.getSize(); + + pages.push({ + index: i, + width, + height, + pdfPageData: undefined, + }); + } + + currentPageIndex = 0; + renderCanvas(); + updatePageNavigation(); + + // Hide upload area and show tool container + uploadArea.classList.add('hidden'); + toolContainer.classList.remove('hidden'); + + // Init icons + setTimeout(() => createIcons({ icons }), 100); + } catch (error) { + console.error('Error loading PDF:', error); + showModal( + 'Error', + 'Error loading PDF file. Please try again with a valid PDF.', + 'error' + ); + } } // Page navigation prevPageBtn.addEventListener('click', () => { - if (currentPageIndex > 0) { - switchToPage(currentPageIndex - 1) - } -}) + if (currentPageIndex > 0) { + switchToPage(currentPageIndex - 1); + } +}); nextPageBtn.addEventListener('click', () => { - if (currentPageIndex < pages.length - 1) { - switchToPage(currentPageIndex + 1) - } -}) + if (currentPageIndex < pages.length - 1) { + switchToPage(currentPageIndex + 1); + } +}); addPageBtn.addEventListener('click', () => { - createBlankPage() - switchToPage(pages.length - 1) -}) + createBlankPage(); + switchToPage(pages.length - 1); +}); resetBtn.addEventListener('click', () => { - if (fields.length > 0 || pages.length > 0) { - if (confirm('Are you sure you want to reset? All your work will be lost.')) { - resetToInitial() - } - } else { - resetToInitial() + if (fields.length > 0 || pages.length > 0) { + if ( + confirm('Are you sure you want to reset? All your work will be lost.') + ) { + resetToInitial(); } -}) + } else { + resetToInitial(); + } +}); // Custom Modal Logic -const errorModal = document.getElementById('errorModal') -const errorModalTitle = document.getElementById('errorModalTitle') -const errorModalMessage = document.getElementById('errorModalMessage') -const errorModalClose = document.getElementById('errorModalClose') +const errorModal = document.getElementById('errorModal'); +const errorModalTitle = document.getElementById('errorModalTitle'); +const errorModalMessage = document.getElementById('errorModalMessage'); +const errorModalClose = document.getElementById('errorModalClose'); -let modalCloseCallback: (() => void) | null = null +let modalCloseCallback: (() => void) | null = null; -function showModal(title: string, message: string, type: 'error' | 'warning' | 'info' = 'error', onClose?: () => void, buttonText: string = 'Close') { - if (!errorModal || !errorModalTitle || !errorModalMessage || !errorModalClose) return +function showModal( + title: string, + message: string, + type: 'error' | 'warning' | 'info' = 'error', + onClose?: () => void, + buttonText: string = 'Close' +) { + if (!errorModal || !errorModalTitle || !errorModalMessage || !errorModalClose) + return; - errorModalTitle.textContent = title - errorModalMessage.textContent = message - errorModalClose.textContent = buttonText + errorModalTitle.textContent = title; + errorModalMessage.textContent = message; + errorModalClose.textContent = buttonText; - modalCloseCallback = onClose || null - errorModal.classList.remove('hidden') + modalCloseCallback = onClose || null; + errorModal.classList.remove('hidden'); } if (errorModalClose) { - errorModalClose.addEventListener('click', () => { - errorModal?.classList.add('hidden') - if (modalCloseCallback) { - modalCloseCallback() - modalCloseCallback = null - } - }) + errorModalClose.addEventListener('click', () => { + errorModal?.classList.add('hidden'); + if (modalCloseCallback) { + modalCloseCallback(); + modalCloseCallback = null; + } + }); } // Close modal on backdrop click if (errorModal) { - errorModal.addEventListener('click', (e) => { - if (e.target === errorModal) { - errorModal.classList.add('hidden') - if (modalCloseCallback) { - modalCloseCallback() - modalCloseCallback = null - } - } - }) + errorModal.addEventListener('click', (e) => { + if (e.target === errorModal) { + errorModal.classList.add('hidden'); + if (modalCloseCallback) { + modalCloseCallback(); + modalCloseCallback = null; + } + } + }); } -initializeGlobalShortcuts() +initializeGlobalShortcuts(); diff --git a/src/js/logic/form-filler-page.ts b/src/js/logic/form-filler-page.ts index 1deb9d1..e7c58af 100644 --- a/src/js/logic/form-filler-page.ts +++ b/src/js/logic/form-filler-page.ts @@ -85,7 +85,7 @@ function resetState() { } const toolUploader = document.getElementById('tool-uploader'); - const isFullWidth = localStorage.getItem('fullWidthMode') === 'true'; + const isFullWidth = localStorage.getItem('fullWidthMode') !== 'false'; if (toolUploader && !isFullWidth) { toolUploader.classList.remove('max-w-6xl'); toolUploader.classList.add('max-w-2xl'); @@ -139,7 +139,8 @@ async function setupFormViewer() { } const toolUploader = document.getElementById('tool-uploader'); - const isFullWidth = localStorage.getItem('fullWidthMode') === 'true'; + // Default to true if not set + const isFullWidth = localStorage.getItem('fullWidthMode') !== 'false'; if (toolUploader && !isFullWidth) { toolUploader.classList.remove('max-w-2xl'); toolUploader.classList.add('max-w-6xl'); diff --git a/src/js/logic/header-footer-page.ts b/src/js/logic/header-footer-page.ts index 5113af9..c2d0dc3 100644 --- a/src/js/logic/header-footer-page.ts +++ b/src/js/logic/header-footer-page.ts @@ -2,9 +2,9 @@ import { createIcons, icons } from 'lucide'; import { showAlert, showLoader, hideLoader } from '../ui.js'; import { downloadFile, hexToRgb, formatBytes, parsePageRanges } from '../utils/helpers.js'; import { PDFDocument as PDFLibDocument, rgb, StandardFonts } from 'pdf-lib'; +import { HeaderFooterState } from '@/types'; -interface PageState { file: File | null; pdfDoc: PDFLibDocument | null; } -const pageState: PageState = { file: null, pdfDoc: null }; +const pageState: HeaderFooterState = { file: null, pdfDoc: null }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initializePage); diff --git a/src/js/logic/image-to-pdf-page.ts b/src/js/logic/image-to-pdf-page.ts index ba20e44..3051aca 100644 --- a/src/js/logic/image-to-pdf-page.ts +++ b/src/js/logic/image-to-pdf-page.ts @@ -1,9 +1,15 @@ import { createIcons, icons } from 'lucide'; import { showAlert, showLoader, hideLoader } from '../ui.js'; -import { downloadFile, readFileAsArrayBuffer, formatBytes } from '../utils/helpers.js'; -import { PDFDocument as PDFLibDocument } from 'pdf-lib'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; +import heic2any from 'heic2any'; + +const SUPPORTED_FORMATS = '.jpg,.jpeg,.png,.bmp,.gif,.tiff,.tif,.pnm,.pgm,.pbm,.ppm,.pam,.jxr,.jpx,.jp2,.psd,.svg,.heic,.heif,.webp'; +const SUPPORTED_FORMATS_DISPLAY = 'JPG, PNG, BMP, GIF, TIFF, PNM, PGM, PBM, PPM, PAM, JXR, JPX, JP2, PSD, SVG, HEIC, WebP'; let files: File[] = []; +let pymupdf: PyMuPDF | null = null; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initializePage); @@ -19,8 +25,14 @@ function initializePage() { const addMoreBtn = document.getElementById('add-more-btn'); const clearFilesBtn = document.getElementById('clear-files-btn'); const processBtn = document.getElementById('process-btn'); + const formatDisplay = document.getElementById('supported-formats'); + + if (formatDisplay) { + formatDisplay.textContent = SUPPORTED_FORMATS_DISPLAY; + } if (fileInput) { + fileInput.accept = SUPPORTED_FORMATS; fileInput.addEventListener('change', handleFileUpload); } @@ -43,7 +55,6 @@ function initializePage() { } }); - // Clear value on click to allow re-selecting the same file fileInput?.addEventListener('click', () => { if (fileInput) fileInput.value = ''; }); @@ -78,13 +89,21 @@ function handleFileUpload(e: Event) { } } +function getFileExtension(filename: string): string { + return '.' + filename.split('.').pop()?.toLowerCase() || ''; +} + +function isValidImageFile(file: File): boolean { + const ext = getFileExtension(file.name); + const validExtensions = SUPPORTED_FORMATS.split(','); + return validExtensions.includes(ext) || file.type.startsWith('image/'); +} + function handleFiles(newFiles: FileList) { - const validFiles = Array.from(newFiles).filter(file => - file.type.startsWith('image/') - ); + const validFiles = Array.from(newFiles).filter(isValidImageFile); if (validFiles.length < newFiles.length) { - showAlert('Invalid Files', 'Some files were skipped. Only image files are allowed.'); + showAlert('Invalid Files', 'Some files were skipped. Only supported image formats are allowed.'); } if (validFiles.length > 0) { @@ -146,95 +165,74 @@ function updateUI() { } } -function sanitizeImageAsJpeg(imageBytes: any) { - return new Promise((resolve, reject) => { - const blob = new Blob([imageBytes]); - const imageUrl = URL.createObjectURL(blob); - const img = new Image(); - - img.onload = () => { - const canvas = document.createElement('canvas'); - canvas.width = img.naturalWidth; - canvas.height = img.naturalHeight; - const ctx = canvas.getContext('2d'); - if (!ctx) { - URL.revokeObjectURL(imageUrl); - return reject(new Error('Could not get canvas context')); - } - ctx.drawImage(img, 0, 0); - - canvas.toBlob( - async (jpegBlob) => { - if (!jpegBlob) { - return reject(new Error('Canvas toBlob conversion failed.')); - } - const arrayBuffer = await jpegBlob.arrayBuffer(); - resolve(new Uint8Array(arrayBuffer)); - }, - 'image/jpeg', - 0.9 - ); - URL.revokeObjectURL(imageUrl); - }; - - img.onerror = () => { - URL.revokeObjectURL(imageUrl); - reject( - new Error( - 'The provided file could not be loaded as an image. It may be corrupted.' - ) - ); - }; - - img.src = imageUrl; - }); +async function ensurePyMuPDF(): Promise { + if (!pymupdf) { + pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); + await pymupdf.load(); + } + return pymupdf; } -// Special handler for SVG files - must read as text -function svgToPng(svgText: string): Promise { - return new Promise((resolve, reject) => { - const img = new Image(); - const svgBlob = new Blob([svgText], { type: 'image/svg+xml;charset=utf-8' }); - const url = URL.createObjectURL(svgBlob); +async function preprocessFile(file: File): Promise { + const ext = getFileExtension(file.name); - img.onload = () => { - const canvas = document.createElement('canvas'); - const width = img.naturalWidth || img.width || 800; - const height = img.naturalHeight || img.height || 600; + if (ext === '.heic' || ext === '.heif') { + try { + const conversionResult = await heic2any({ + blob: file, + toType: 'image/png', + quality: 0.9, + }); - canvas.width = width; - canvas.height = height; + const blob = Array.isArray(conversionResult) ? conversionResult[0] : conversionResult; + return new File([blob], file.name.replace(/\.(heic|heif)$/i, '.png'), { type: 'image/png' }); + } catch (e) { + console.error(`Failed to convert HEIC: ${file.name}`, e); + throw new Error(`Failed to process HEIC file: ${file.name}`); + } + } - const ctx = canvas.getContext('2d'); - if (!ctx) { - URL.revokeObjectURL(url); - return reject(new Error('Could not get canvas context')); - } + if (ext === '.webp') { + try { + return await new Promise((resolve, reject) => { + const img = new Image(); + const url = URL.createObjectURL(file); - ctx.fillStyle = 'white'; - ctx.fillRect(0, 0, width, height); - ctx.drawImage(img, 0, 0, width, height); - - canvas.toBlob( - async (pngBlob) => { - URL.revokeObjectURL(url); - if (!pngBlob) { - return reject(new Error('Canvas toBlob conversion failed.')); + img.onload = () => { + const canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + const ctx = canvas.getContext('2d'); + if (!ctx) { + URL.revokeObjectURL(url); + reject(new Error('Canvas context failed')); + return; } - const arrayBuffer = await pngBlob.arrayBuffer(); - resolve(new Uint8Array(arrayBuffer)); - }, - 'image/png' - ); - }; + ctx.drawImage(img, 0, 0); + canvas.toBlob((blob) => { + URL.revokeObjectURL(url); + if (blob) { + resolve(new File([blob], file.name.replace(/\.webp$/i, '.png'), { type: 'image/png' })); + } else { + reject(new Error('Canvas toBlob failed')); + } + }, 'image/png'); + }; - img.onerror = () => { - URL.revokeObjectURL(url); - reject(new Error('Failed to load SVG image')); - }; + img.onerror = () => { + URL.revokeObjectURL(url); + reject(new Error('Failed to load WebP image')); + }; - img.src = url; - }); + img.src = url; + }); + } catch (e) { + console.error(`Failed to convert WebP: ${file.name}`, e); + throw new Error(`Failed to process WebP file: ${file.name}`); + } + } + + return file; } async function convertToPdf() { @@ -243,78 +241,34 @@ async function convertToPdf() { return; } - showLoader('Creating PDF from images...'); + showLoader('Processing images...'); try { - const pdfDoc = await PDFLibDocument.create(); - + const processedFiles: File[] = []; for (const file of files) { try { - const isSvg = file.type === 'image/svg+xml' || file.name.toLowerCase().endsWith('.svg'); - - if (isSvg) { - // Handle SVG files - read as text - const svgText = await file.text(); - const pngBytes = await svgToPng(svgText); - const pngImage = await pdfDoc.embedPng(pngBytes); - - const page = pdfDoc.addPage([pngImage.width, pngImage.height]); - page.drawImage(pngImage, { - x: 0, - y: 0, - width: pngImage.width, - height: pngImage.height, - }); - } else if (file.type === 'image/png') { - // Handle PNG files - const originalBytes = await readFileAsArrayBuffer(file); - const pngImage = await pdfDoc.embedPng(originalBytes as Uint8Array); - - const page = pdfDoc.addPage([pngImage.width, pngImage.height]); - page.drawImage(pngImage, { - x: 0, - y: 0, - width: pngImage.width, - height: pngImage.height, - }); - } else { - // Handle JPG/other raster images - const originalBytes = await readFileAsArrayBuffer(file); - let jpgImage; - - try { - jpgImage = await pdfDoc.embedJpg(originalBytes as Uint8Array); - } catch (e) { - // Fallback: convert to JPEG via canvas - const sanitizedBytes = await sanitizeImageAsJpeg(originalBytes); - jpgImage = await pdfDoc.embedJpg(sanitizedBytes as Uint8Array); - } - - const page = pdfDoc.addPage([jpgImage.width, jpgImage.height]); - page.drawImage(jpgImage, { - x: 0, - y: 0, - width: jpgImage.width, - height: jpgImage.height, - }); - } - } catch (error) { - console.error(`Failed to process ${file.name}:`, error); - throw new Error(`Could not process "${file.name}". The file may be corrupted.`); + const processed = await preprocessFile(file); + processedFiles.push(processed); + } catch (error: any) { + console.warn(error); + throw error; } } - const pdfBytes = await pdfDoc.save(); - downloadFile( - new Blob([new Uint8Array(pdfBytes)], { type: 'application/pdf' }), - 'from_images.pdf' - ); + showLoader('Loading engine...'); + const mupdf = await ensurePyMuPDF(); + + showLoader('Converting images to PDF...'); + const pdfBlob = await mupdf.imagesToPdf(processedFiles); + + downloadFile(pdfBlob, 'images_to_pdf.pdf'); + showAlert('Success', 'PDF created successfully!', 'success', () => { resetState(); }); } catch (e: any) { - console.error(e); - showAlert('Conversion Error', e.message); + console.error('[ImageToPDF]', e); + showAlert('Conversion Error', e.message || 'Failed to convert images to PDF.'); } finally { hideLoader(); } diff --git a/src/js/logic/invert-colors-page.ts b/src/js/logic/invert-colors-page.ts index 1ae6971..4d27554 100644 --- a/src/js/logic/invert-colors-page.ts +++ b/src/js/logic/invert-colors-page.ts @@ -3,11 +3,11 @@ import { showAlert, showLoader, hideLoader } from '../ui.js'; import { downloadFile, formatBytes, getPDFDocument } from '../utils/helpers.js'; import { PDFDocument as PDFLibDocument } from 'pdf-lib'; import * as pdfjsLib from 'pdfjs-dist'; +import { InvertColorsState } from '@/types'; pdfjsLib.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString(); -interface PageState { file: File | null; pdfDoc: PDFLibDocument | null; } -const pageState: PageState = { file: null, pdfDoc: null }; +const pageState: InvertColorsState = { file: null, pdfDoc: null }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initializePage); } else { initializePage(); } diff --git a/src/js/logic/jpg-to-pdf-page.ts b/src/js/logic/jpg-to-pdf-page.ts index f657c80..40264cd 100644 --- a/src/js/logic/jpg-to-pdf-page.ts +++ b/src/js/logic/jpg-to-pdf-page.ts @@ -1,9 +1,14 @@ import { createIcons, icons } from 'lucide'; import { showAlert, showLoader, hideLoader } from '../ui.js'; -import { downloadFile, readFileAsArrayBuffer, formatBytes } from '../utils/helpers.js'; -import { PDFDocument as PDFLibDocument } from 'pdf-lib'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +const SUPPORTED_FORMATS = '.jpg,.jpeg,.jp2,.jpx'; +const SUPPORTED_MIME_TYPES = ['image/jpeg', 'image/jpg', 'image/jp2']; let files: File[] = []; +let pymupdf: PyMuPDF | null = null; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initializePage); @@ -43,7 +48,6 @@ function initializePage() { } }); - // Clear value on click to allow re-selecting the same file fileInput?.addEventListener('click', () => { if (fileInput) fileInput.value = ''; }); @@ -78,13 +82,21 @@ function handleFileUpload(e: Event) { } } +function getFileExtension(filename: string): string { + return '.' + (filename.split('.').pop()?.toLowerCase() || ''); +} + +function isValidImageFile(file: File): boolean { + const ext = getFileExtension(file.name); + const validExtensions = SUPPORTED_FORMATS.split(','); + return validExtensions.includes(ext) || SUPPORTED_MIME_TYPES.includes(file.type); +} + function handleFiles(newFiles: FileList) { - const validFiles = Array.from(newFiles).filter(file => - file.type === 'image/jpeg' || file.type === 'image/jpg' || file.name.toLowerCase().endsWith('.jpg') || file.name.toLowerCase().endsWith('.jpeg') - ); + const validFiles = Array.from(newFiles).filter(isValidImageFile); if (validFiles.length < newFiles.length) { - showAlert('Invalid Files', 'Some files were skipped. Only JPG/JPEG images are allowed.'); + showAlert('Invalid Files', 'Some files were skipped. Only JPG, JPEG, JP2, and JPX files are allowed.'); } if (validFiles.length > 0) { @@ -146,102 +158,37 @@ function updateUI() { } } -function sanitizeImageAsJpeg(imageBytes: any) { - return new Promise((resolve, reject) => { - const blob = new Blob([imageBytes]); - const imageUrl = URL.createObjectURL(blob); - const img = new Image(); - - img.onload = () => { - const canvas = document.createElement('canvas'); - canvas.width = img.naturalWidth; - canvas.height = img.naturalHeight; - const ctx = canvas.getContext('2d'); - ctx.drawImage(img, 0, 0); - - canvas.toBlob( - async (jpegBlob) => { - if (!jpegBlob) { - return reject(new Error('Canvas toBlob conversion failed.')); - } - const arrayBuffer = await jpegBlob.arrayBuffer(); - resolve(new Uint8Array(arrayBuffer)); - }, - 'image/jpeg', - 0.9 - ); - URL.revokeObjectURL(imageUrl); - }; - - img.onerror = () => { - URL.revokeObjectURL(imageUrl); - reject( - new Error( - 'The provided file could not be loaded as an image. It may be corrupted.' - ) - ); - }; - - img.src = imageUrl; - }); +async function ensurePyMuPDF(): Promise { + if (!pymupdf) { + pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); + await pymupdf.load(); + } + return pymupdf; } async function convertToPdf() { if (files.length === 0) { - showAlert('No Files', 'Please select at least one JPG file.'); + showAlert('No Files', 'Please select at least one JPG or JPEG2000 image.'); return; } - showLoader('Creating PDF from JPGs...'); + showLoader('Loading engine...'); try { - const pdfDoc = await PDFLibDocument.create(); + const mupdf = await ensurePyMuPDF(); - for (const file of files) { - const originalBytes = await readFileAsArrayBuffer(file); - let jpgImage; + showLoader('Converting images to PDF...'); - try { - jpgImage = await pdfDoc.embedJpg(originalBytes as Uint8Array); - } catch (e) { - showAlert( - 'Warning', - `Direct JPG embedding failed for ${file.name}, attempting to sanitize...` - ); - try { - const sanitizedBytes = await sanitizeImageAsJpeg(originalBytes); - jpgImage = await pdfDoc.embedJpg(sanitizedBytes as Uint8Array); - } catch (fallbackError) { - console.error( - `Failed to process ${file.name} after sanitization:`, - fallbackError - ); - throw new Error( - `Could not process "${file.name}". The file may be corrupted.` - ); - } - } + const pdfBlob = await mupdf.imagesToPdf(files); - const page = pdfDoc.addPage([jpgImage.width, jpgImage.height]); - page.drawImage(jpgImage, { - x: 0, - y: 0, - width: jpgImage.width, - height: jpgImage.height, - }); - } + downloadFile(pdfBlob, 'from_jpgs.pdf'); - const pdfBytes = await pdfDoc.save(); - downloadFile( - new Blob([new Uint8Array(pdfBytes)], { type: 'application/pdf' }), - 'from_jpgs.pdf' - ); showAlert('Success', 'PDF created successfully!', 'success', () => { resetState(); }); } catch (e: any) { - console.error(e); - showAlert('Conversion Error', e.message); + console.error('[JpgToPdf]', e); + showAlert('Conversion Error', e.message || 'Failed to convert images to PDF.'); } finally { hideLoader(); } diff --git a/src/js/logic/linearize-pdf-page.ts b/src/js/logic/linearize-pdf-page.ts index d6d5121..f9db90f 100644 --- a/src/js/logic/linearize-pdf-page.ts +++ b/src/js/logic/linearize-pdf-page.ts @@ -2,12 +2,9 @@ import { showAlert } from '../ui.js'; import { downloadFile, formatBytes, initializeQpdf, readFileAsArrayBuffer } from '../utils/helpers.js'; import { icons, createIcons } from 'lucide'; import JSZip from 'jszip'; +import { LinearizePdfState } from '@/types'; -interface PageState { - files: File[]; -} - -const pageState: PageState = { +const pageState: LinearizePdfState = { files: [], }; diff --git a/src/js/logic/markdown-to-pdf-page.ts b/src/js/logic/markdown-to-pdf-page.ts new file mode 100644 index 0000000..e104c98 --- /dev/null +++ b/src/js/logic/markdown-to-pdf-page.ts @@ -0,0 +1,21 @@ +import { MarkdownEditor } from '../utils/markdown-editor.js'; + +document.addEventListener('DOMContentLoaded', () => { + const container = document.getElementById('markdown-editor-container'); + + if (!container) { + console.error('Markdown editor container not found'); + return; + } + + const editor = new MarkdownEditor(container, {}); + + console.log('Markdown editor initialized'); + + const backButton = document.getElementById('back-to-tools'); + if (backButton) { + backButton.addEventListener('click', () => { + window.location.href = '/'; + }); + } +}); diff --git a/src/js/logic/mobi-to-pdf-page.ts b/src/js/logic/mobi-to-pdf-page.ts new file mode 100644 index 0000000..f55dcc6 --- /dev/null +++ b/src/js/logic/mobi-to-pdf-page.ts @@ -0,0 +1,202 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +const FILETYPE = 'mobi'; +const EXTENSIONS = ['.mobi']; +const TOOL_NAME = 'MOBI'; + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!fileDisplayArea || !processBtn || !fileControls) return; + + if (state.files.length > 0) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + fileControls.classList.remove('hidden'); + processBtn.classList.remove('hidden'); + (processBtn as HTMLButtonElement).disabled = false; + } else { + fileDisplayArea.innerHTML = ''; + fileControls.classList.add('hidden'); + processBtn.classList.add('hidden'); + (processBtn as HTMLButtonElement).disabled = true; + } + }; + + const resetState = () => { + state.files = []; + state.pdfDoc = null; + updateUI(); + }; + + const convertToPdf = async () => { + try { + if (state.files.length === 0) { + showAlert('No Files', `Please select at least one ${TOOL_NAME} file.`); + return; + } + + showLoader('Loading engine...'); + const pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); + await pymupdf.load(); + + if (state.files.length === 1) { + const originalFile = state.files[0]; + showLoader(`Converting ${originalFile.name}...`); + + const pdfBlob = await pymupdf.convertToPdf(originalFile, { filetype: FILETYPE }); + const fileName = originalFile.name.replace(/\.[^.]+$/, '') + '.pdf'; + + downloadFile(pdfBlob, fileName); + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${originalFile.name} to PDF.`, + 'success', + () => resetState() + ); + } else { + showLoader('Converting files...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + + const pdfBlob = await pymupdf.convertToPdf(file, { filetype: FILETYPE }); + const baseName = file.name.replace(/\.[^.]+$/, ''); + const pdfBuffer = await pdfBlob.arrayBuffer(); + zip.file(`${baseName}.pdf`, pdfBuffer); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, `${FILETYPE}-converted.zip`); + + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${state.files.length} ${TOOL_NAME} file(s) to PDF.`, + 'success', + () => resetState() + ); + } + } catch (e: any) { + console.error(`[${TOOL_NAME}2PDF] ERROR:`, e); + hideLoader(); + showAlert('Error', `An error occurred during conversion. Error: ${e.message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + state.files = [...state.files, ...Array.from(files)]; + updateUI(); + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const files = e.dataTransfer?.files; + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(f => { + const name = f.name.toLowerCase(); + return EXTENSIONS.some(ext => name.endsWith(ext)); + }); + if (validFiles.length > 0) { + const dataTransfer = new DataTransfer(); + validFiles.forEach(f => dataTransfer.items.add(f)); + handleFileSelect(dataTransfer.files); + } + } + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => { + fileInput.click(); + }); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', () => { + resetState(); + }); + } + + if (processBtn) { + processBtn.addEventListener('click', convertToPdf); + } +}); diff --git a/src/js/logic/ocr-pdf-page.ts b/src/js/logic/ocr-pdf-page.ts index 1c62745..422ae66 100644 --- a/src/js/logic/ocr-pdf-page.ts +++ b/src/js/logic/ocr-pdf-page.ts @@ -2,566 +2,680 @@ import { tesseractLanguages } from '../config/tesseract-languages.js'; import { showAlert } from '../ui.js'; import { downloadFile, formatBytes, getPDFDocument } from '../utils/helpers.js'; import Tesseract from 'tesseract.js'; -import { PDFDocument as PDFLibDocument, StandardFonts, rgb } from 'pdf-lib'; +import { + PDFDocument as PDFLibDocument, + StandardFonts, + rgb, + PDFFont, +} from 'pdf-lib'; import fontkit from '@pdf-lib/fontkit'; import { icons, createIcons } from 'lucide'; import * as pdfjsLib from 'pdfjs-dist'; import { getFontForLanguage } from '../utils/font-loader.js'; +import { OcrState, OcrLine, OcrPage } from '@/types'; +import { + parseHocrDocument, + calculateWordTransform, + calculateSpaceTransform, +} from '../utils/hocr-transform.js'; -pdfjsLib.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString(); - -interface Word { - text: string; - bbox: { x0: number; y0: number; x1: number; y1: number }; - confidence: number; -} - -interface OcrState { - file: File | null; - searchablePdfBytes: Uint8Array | null; -} +pdfjsLib.GlobalWorkerOptions.workerSrc = new URL( + 'pdfjs-dist/build/pdf.worker.min.mjs', + import.meta.url +).toString(); const pageState: OcrState = { - file: null, - searchablePdfBytes: null, + file: null, + searchablePdfBytes: null, }; const whitelistPresets: Record = { - alphanumeric: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .,!?-\'"', - 'numbers-currency': '0123456789$€£¥.,- ', - 'letters-only': 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ', - 'numbers-only': '0123456789', - invoice: '0123456789$.,/-#: ', - forms: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .,()-_/@#:', + alphanumeric: + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .,!?-\'"', + 'numbers-currency': '0123456789$€£¥.,- ', + 'letters-only': 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ', + 'numbers-only': '0123456789', + invoice: '0123456789$.,/-#: ', + forms: + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .,()-_/@#:', }; -function parseHOCR(hocrText: string): Word[] { - const parser = new DOMParser(); - const doc = parser.parseFromString(hocrText, 'text/html'); - const words: Word[] = []; +function drawOcrTextLayer( + page: ReturnType, + ocrPage: OcrPage, + pageHeight: number, + primaryFont: PDFFont, + latinFont: PDFFont +): void { + ocrPage.lines.forEach(function (line: OcrLine) { + const words = line.words; - const wordElements = doc.querySelectorAll('.ocrx_word'); + for (let i = 0; i < words.length; i++) { + const word = words[i]; + const text = word.text.replace( + /[\u0000-\u001F\u007F-\u009F\u200E\u200F\u202A-\u202E\uFEFF]/g, + '' + ); - wordElements.forEach(function (wordEl) { - const titleAttr = wordEl.getAttribute('title'); - const text = wordEl.textContent?.trim() || ''; + if (!text.trim()) continue; - if (!titleAttr || !text) return; + const hasNonLatin = /[^\u0000-\u007F]/.test(text); + const font = hasNonLatin ? primaryFont : latinFont; - const bboxMatch = titleAttr.match(/bbox (\d+) (\d+) (\d+) (\d+)/); - const confMatch = titleAttr.match(/x_wconf (\d+)/); + if (!font) { + console.warn('Font not available for text: "' + text + '"'); + continue; + } - if (bboxMatch) { - words.push({ - text: text, - bbox: { - x0: parseInt(bboxMatch[1]), - y0: parseInt(bboxMatch[2]), - x1: parseInt(bboxMatch[3]), - y1: parseInt(bboxMatch[4]), - }, - confidence: confMatch ? parseInt(confMatch[1]) : 0, - }); + const transform = calculateWordTransform( + word, + line, + pageHeight, + (txt: string, size: number) => { + try { + return font.widthOfTextAtSize(txt, size); + } catch { + return 0; + } } - }); + ); - return words; + if (transform.fontSize <= 0) continue; + + try { + page.drawText(text, { + x: transform.x, + y: transform.y, + font, + size: transform.fontSize, + color: rgb(0, 0, 0), + opacity: 0, + }); + } catch (error) { + console.warn(`Could not draw text "${text}":`, error); + } + + if (line.injectWordBreaks && i < words.length - 1) { + const nextWord = words[i + 1]; + const spaceTransform = calculateSpaceTransform( + word, + nextWord, + line, + pageHeight, + (size: number) => { + try { + return font.widthOfTextAtSize(' ', size); + } catch { + return 0; + } + } + ); + + if (spaceTransform && spaceTransform.horizontalScale > 0.1) { + try { + page.drawText(' ', { + x: spaceTransform.x, + y: spaceTransform.y, + font, + size: spaceTransform.fontSize, + color: rgb(0, 0, 0), + opacity: 0, + }); + } catch { + console.warn(`Could not draw space between words`); + } + } + } + } + }); } function binarizeCanvas(ctx: CanvasRenderingContext2D) { - const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); - const data = imageData.data; - for (let i = 0; i < data.length; i += 4) { - const brightness = 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2]; - const color = brightness > 128 ? 255 : 0; - data[i] = data[i + 1] = data[i + 2] = color; - } - ctx.putImageData(imageData, 0, 0); + const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); + const data = imageData.data; + for (let i = 0; i < data.length; i += 4) { + const brightness = + 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2]; + const color = brightness > 128 ? 255 : 0; + data[i] = data[i + 1] = data[i + 2] = color; + } + ctx.putImageData(imageData, 0, 0); } function updateProgress(status: string, progress: number) { - const progressBar = document.getElementById('progress-bar'); - const progressStatus = document.getElementById('progress-status'); - const progressLog = document.getElementById('progress-log'); + const progressBar = document.getElementById('progress-bar'); + const progressStatus = document.getElementById('progress-status'); + const progressLog = document.getElementById('progress-log'); - if (!progressBar || !progressStatus || !progressLog) return; + if (!progressBar || !progressStatus || !progressLog) return; - progressStatus.textContent = status; - progressBar.style.width = `${Math.min(100, progress * 100)}%`; + progressStatus.textContent = status; + progressBar.style.width = `${Math.min(100, progress * 100)}%`; - const logMessage = `Status: ${status}`; - progressLog.textContent += logMessage + '\n'; - progressLog.scrollTop = progressLog.scrollHeight; + const logMessage = `Status: ${status}`; + progressLog.textContent += logMessage + '\n'; + progressLog.scrollTop = progressLog.scrollHeight; } function resetState() { - pageState.file = null; - pageState.searchablePdfBytes = null; + pageState.file = null; + pageState.searchablePdfBytes = null; - const fileDisplayArea = document.getElementById('file-display-area'); - if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + const fileDisplayArea = document.getElementById('file-display-area'); + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; - const toolOptions = document.getElementById('tool-options'); - if (toolOptions) toolOptions.classList.add('hidden'); + const toolOptions = document.getElementById('tool-options'); + if (toolOptions) toolOptions.classList.add('hidden'); - const ocrProgress = document.getElementById('ocr-progress'); - if (ocrProgress) ocrProgress.classList.add('hidden'); + const ocrProgress = document.getElementById('ocr-progress'); + if (ocrProgress) ocrProgress.classList.add('hidden'); - const ocrResults = document.getElementById('ocr-results'); - if (ocrResults) ocrResults.classList.add('hidden'); + const ocrResults = document.getElementById('ocr-results'); + if (ocrResults) ocrResults.classList.add('hidden'); - const progressLog = document.getElementById('progress-log'); - if (progressLog) progressLog.textContent = ''; + const progressLog = document.getElementById('progress-log'); + if (progressLog) progressLog.textContent = ''; - const progressBar = document.getElementById('progress-bar'); - if (progressBar) progressBar.style.width = '0%'; + const progressBar = document.getElementById('progress-bar'); + if (progressBar) progressBar.style.width = '0%'; - const fileInput = document.getElementById('file-input') as HTMLInputElement; - if (fileInput) fileInput.value = ''; + const fileInput = document.getElementById('file-input') as HTMLInputElement; + if (fileInput) fileInput.value = ''; - // Reset selected languages - const langCheckboxes = document.querySelectorAll('.lang-checkbox') as NodeListOf; - langCheckboxes.forEach(function (cb) { cb.checked = false; }); + // Reset selected languages + const langCheckboxes = document.querySelectorAll( + '.lang-checkbox' + ) as NodeListOf; + langCheckboxes.forEach(function (cb) { + cb.checked = false; + }); - const selectedLangsDisplay = document.getElementById('selected-langs-display'); - if (selectedLangsDisplay) selectedLangsDisplay.textContent = 'None'; + const selectedLangsDisplay = document.getElementById( + 'selected-langs-display' + ); + if (selectedLangsDisplay) selectedLangsDisplay.textContent = 'None'; - const processBtn = document.getElementById('process-btn') as HTMLButtonElement; - if (processBtn) processBtn.disabled = true; + const processBtn = document.getElementById( + 'process-btn' + ) as HTMLButtonElement; + if (processBtn) processBtn.disabled = true; } async function runOCR() { - const selectedLangs = Array.from( - document.querySelectorAll('.lang-checkbox:checked') - ).map(function (cb) { return (cb as HTMLInputElement).value; }); + const selectedLangs = Array.from( + document.querySelectorAll('.lang-checkbox:checked') + ).map(function (cb) { + return (cb as HTMLInputElement).value; + }); - const scale = parseFloat( - (document.getElementById('ocr-resolution') as HTMLSelectElement).value + const scale = parseFloat( + (document.getElementById('ocr-resolution') as HTMLSelectElement).value + ); + const binarize = (document.getElementById('ocr-binarize') as HTMLInputElement) + .checked; + const whitelist = ( + document.getElementById('ocr-whitelist') as HTMLInputElement + ).value; + + if (selectedLangs.length === 0) { + showAlert( + 'No Languages Selected', + 'Please select at least one language for OCR.' ); - const binarize = (document.getElementById('ocr-binarize') as HTMLInputElement).checked; - const whitelist = (document.getElementById('ocr-whitelist') as HTMLInputElement).value; + return; + } - if (selectedLangs.length === 0) { - showAlert('No Languages Selected', 'Please select at least one language for OCR.'); - return; + if (!pageState.file) { + showAlert('No File', 'Please upload a PDF file first.'); + return; + } + + const langString = selectedLangs.join('+'); + + const toolOptions = document.getElementById('tool-options'); + const ocrProgress = document.getElementById('ocr-progress'); + + if (toolOptions) toolOptions.classList.add('hidden'); + if (ocrProgress) ocrProgress.classList.remove('hidden'); + + try { + const worker = await Tesseract.createWorker(langString, 1, { + logger: function (m: { status: string; progress: number }) { + updateProgress(m.status, m.progress || 0); + }, + }); + + await worker.setParameters({ + tessjs_create_hocr: '1', + tessedit_pageseg_mode: Tesseract.PSM.AUTO, + }); + + if (whitelist) { + await worker.setParameters({ + tessedit_char_whitelist: whitelist, + }); } - if (!pageState.file) { - showAlert('No File', 'Please upload a PDF file first.'); - return; - } + const arrayBuffer = await pageState.file.arrayBuffer(); + const pdf = await getPDFDocument({ data: arrayBuffer }).promise; + const newPdfDoc = await PDFLibDocument.create(); - const langString = selectedLangs.join('+'); + newPdfDoc.registerFontkit(fontkit); - const toolOptions = document.getElementById('tool-options'); - const ocrProgress = document.getElementById('ocr-progress'); + updateProgress('Loading fonts...', 0); - if (toolOptions) toolOptions.classList.add('hidden'); - if (ocrProgress) ocrProgress.classList.remove('hidden'); + const cjkLangs = ['jpn', 'chi_sim', 'chi_tra', 'kor']; + const indicLangs = [ + 'hin', + 'ben', + 'guj', + 'kan', + 'mal', + 'ori', + 'pan', + 'tam', + 'tel', + 'sin', + ]; + const priorityLangs = [...cjkLangs, ...indicLangs, 'ara', 'rus', 'ukr']; + + const primaryLang = + selectedLangs.find(function (l) { + return priorityLangs.includes(l); + }) || + selectedLangs[0] || + 'eng'; + + const hasCJK = selectedLangs.some(function (l) { + return cjkLangs.includes(l); + }); + const hasIndic = selectedLangs.some(function (l) { + return indicLangs.includes(l); + }); + const hasLatin = + selectedLangs.some(function (l) { + return !priorityLangs.includes(l); + }) || selectedLangs.includes('eng'); + const isIndicPlusLatin = hasIndic && hasLatin && !hasCJK; + + let primaryFont; + let latinFont; try { - const worker = await Tesseract.createWorker(langString, 1, { - logger: function (m: { status: string; progress: number }) { - updateProgress(m.status, m.progress || 0); - }, + if (isIndicPlusLatin) { + const [scriptFontBytes, latinFontBytes] = await Promise.all([ + getFontForLanguage(primaryLang), + getFontForLanguage('eng'), + ]); + primaryFont = await newPdfDoc.embedFont(scriptFontBytes, { + subset: false, }); - - await worker.setParameters({ - tessjs_create_hocr: '1', - tessedit_pageseg_mode: Tesseract.PSM.AUTO, + latinFont = await newPdfDoc.embedFont(latinFontBytes, { + subset: false, }); - - if (whitelist) { - await worker.setParameters({ - tessedit_char_whitelist: whitelist, - }); - } - - const arrayBuffer = await pageState.file.arrayBuffer(); - const pdf = await getPDFDocument({ data: arrayBuffer }).promise; - const newPdfDoc = await PDFLibDocument.create(); - - newPdfDoc.registerFontkit(fontkit); - - updateProgress('Loading fonts...', 0); - - const cjkLangs = ['jpn', 'chi_sim', 'chi_tra', 'kor']; - const indicLangs = ['hin', 'ben', 'guj', 'kan', 'mal', 'ori', 'pan', 'tam', 'tel', 'sin']; - const priorityLangs = [...cjkLangs, ...indicLangs, 'ara', 'rus', 'ukr']; - - const primaryLang = selectedLangs.find(function (l) { return priorityLangs.includes(l); }) || selectedLangs[0] || 'eng'; - - const hasCJK = selectedLangs.some(function (l) { return cjkLangs.includes(l); }); - const hasIndic = selectedLangs.some(function (l) { return indicLangs.includes(l); }); - const hasLatin = selectedLangs.some(function (l) { return !priorityLangs.includes(l); }) || selectedLangs.includes('eng'); - const isIndicPlusLatin = hasIndic && hasLatin && !hasCJK; - - let primaryFont; - let latinFont; - - try { - if (isIndicPlusLatin) { - const [scriptFontBytes, latinFontBytes] = await Promise.all([ - getFontForLanguage(primaryLang), - getFontForLanguage('eng') - ]); - primaryFont = await newPdfDoc.embedFont(scriptFontBytes, { subset: false }); - latinFont = await newPdfDoc.embedFont(latinFontBytes, { subset: false }); - } else { - const fontBytes = await getFontForLanguage(primaryLang); - primaryFont = await newPdfDoc.embedFont(fontBytes, { subset: false }); - latinFont = primaryFont; - } - } catch (e) { - console.error('Font loading failed, falling back to Helvetica', e); - primaryFont = await newPdfDoc.embedFont(StandardFonts.Helvetica); - latinFont = primaryFont; - showAlert('Font Warning', 'Could not load the specific font for this language. Some characters may not appear correctly.'); - } - - let fullText = ''; - - for (let i = 1; i <= pdf.numPages; i++) { - updateProgress(`Processing page ${i} of ${pdf.numPages}`, (i - 1) / pdf.numPages); - - const page = await pdf.getPage(i); - const viewport = page.getViewport({ scale }); - - const canvas = document.createElement('canvas'); - canvas.width = viewport.width; - canvas.height = viewport.height; - const context = canvas.getContext('2d')!; - - await page.render({ canvasContext: context, viewport, canvas }).promise; - - if (binarize) { - binarizeCanvas(context); - } - - const result = await worker.recognize(canvas, {}, { text: true, hocr: true }); - const data = result.data; - - const newPage = newPdfDoc.addPage([viewport.width, viewport.height]); - - const pngImageBytes = await new Promise(function (resolve) { - canvas.toBlob(function (blob) { - const reader = new FileReader(); - reader.onload = function () { - resolve(new Uint8Array(reader.result as ArrayBuffer)); - }; - reader.readAsArrayBuffer(blob!); - }, 'image/png'); - }); - - const pngImage = await newPdfDoc.embedPng(pngImageBytes); - newPage.drawImage(pngImage, { - x: 0, - y: 0, - width: viewport.width, - height: viewport.height, - }); - - if (data.hocr) { - const words = parseHOCR(data.hocr); - - words.forEach(function (word: Word) { - const { x0, y0, x1, y1 } = word.bbox; - const text = word.text.replace(/[\u0000-\u001F\u007F-\u009F\u200E\u200F\u202A-\u202E\uFEFF]/g, ''); - - if (!text.trim()) return; - - const hasNonLatin = /[^\u0000-\u007F]/.test(text); - const font = hasNonLatin ? primaryFont : latinFont; - - if (!font) { - console.warn(`Font not available for text: "${text}"`); - return; - } - - const bboxWidth = x1 - x0; - const bboxHeight = y1 - y0; - - if (bboxWidth <= 0 || bboxHeight <= 0) { - return; - } - - let fontSize = bboxHeight * 0.9; - try { - let textWidth = font.widthOfTextAtSize(text, fontSize); - while (textWidth > bboxWidth && fontSize > 1) { - fontSize -= 0.5; - textWidth = font.widthOfTextAtSize(text, fontSize); - } - } catch (error) { - console.warn(`Could not calculate text width for "${text}":`, error); - return; - } - - try { - newPage.drawText(text, { - x: x0, - y: viewport.height - y1 + (bboxHeight - fontSize) / 2, - font, - size: fontSize, - color: rgb(0, 0, 0), - opacity: 0, - }); - } catch (error) { - console.warn(`Could not draw text "${text}":`, error); - } - }); - } - - fullText += data.text + '\n\n'; - } - - await worker.terminate(); - - pageState.searchablePdfBytes = await newPdfDoc.save(); - - const ocrResults = document.getElementById('ocr-results'); - if (ocrProgress) ocrProgress.classList.add('hidden'); - if (ocrResults) ocrResults.classList.remove('hidden'); - - createIcons({ icons }); - - const textOutput = document.getElementById('ocr-text-output') as HTMLTextAreaElement; - if (textOutput) textOutput.value = fullText.trim(); - + } else { + const fontBytes = await getFontForLanguage(primaryLang); + primaryFont = await newPdfDoc.embedFont(fontBytes, { subset: false }); + latinFont = primaryFont; + } } catch (e) { - console.error(e); - showAlert('OCR Error', 'An error occurred during the OCR process. The worker may have failed to load. Please try again.'); - if (toolOptions) toolOptions.classList.remove('hidden'); - if (ocrProgress) ocrProgress.classList.add('hidden'); + console.error('Font loading failed, falling back to Helvetica', e); + primaryFont = await newPdfDoc.embedFont(StandardFonts.Helvetica); + latinFont = primaryFont; + showAlert( + 'Font Warning', + 'Could not load the specific font for this language. Some characters may not appear correctly.' + ); } + + let fullText = ''; + + for (let i = 1; i <= pdf.numPages; i++) { + updateProgress( + `Processing page ${i} of ${pdf.numPages}`, + (i - 1) / pdf.numPages + ); + + const page = await pdf.getPage(i); + const viewport = page.getViewport({ scale }); + + const canvas = document.createElement('canvas'); + canvas.width = viewport.width; + canvas.height = viewport.height; + const context = canvas.getContext('2d')!; + + await page.render({ canvasContext: context, viewport, canvas }).promise; + + if (binarize) { + binarizeCanvas(context); + } + + const result = await worker.recognize( + canvas, + {}, + { text: true, hocr: true } + ); + const data = result.data; + + const newPage = newPdfDoc.addPage([viewport.width, viewport.height]); + + const pngImageBytes = await new Promise(function (resolve) { + canvas.toBlob(function (blob) { + const reader = new FileReader(); + reader.onload = function () { + resolve(new Uint8Array(reader.result as ArrayBuffer)); + }; + reader.readAsArrayBuffer(blob!); + }, 'image/png'); + }); + + const pngImage = await newPdfDoc.embedPng(pngImageBytes); + newPage.drawImage(pngImage, { + x: 0, + y: 0, + width: viewport.width, + height: viewport.height, + }); + + if (data.hocr) { + const ocrPage = parseHocrDocument(data.hocr); + drawOcrTextLayer( + newPage, + ocrPage, + viewport.height, + primaryFont, + latinFont + ); + } + + fullText += data.text + '\n\n'; + } + + await worker.terminate(); + + pageState.searchablePdfBytes = await newPdfDoc.save(); + + const ocrResults = document.getElementById('ocr-results'); + if (ocrProgress) ocrProgress.classList.add('hidden'); + if (ocrResults) ocrResults.classList.remove('hidden'); + + createIcons({ icons }); + + const textOutput = document.getElementById( + 'ocr-text-output' + ) as HTMLTextAreaElement; + if (textOutput) textOutput.value = fullText.trim(); + } catch (e) { + console.error(e); + showAlert( + 'OCR Error', + 'An error occurred during the OCR process. The worker may have failed to load. Please try again.' + ); + if (toolOptions) toolOptions.classList.remove('hidden'); + if (ocrProgress) ocrProgress.classList.add('hidden'); + } } async function updateUI() { - const fileDisplayArea = document.getElementById('file-display-area'); - const toolOptions = document.getElementById('tool-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const toolOptions = document.getElementById('tool-options'); - if (!fileDisplayArea) return; + if (!fileDisplayArea) return; - fileDisplayArea.innerHTML = ''; + fileDisplayArea.innerHTML = ''; - if (pageState.file) { - const fileDiv = document.createElement('div'); - fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + if (pageState.file) { + const fileDiv = document.createElement('div'); + fileDiv.className = + 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; - const infoContainer = document.createElement('div'); - infoContainer.className = 'flex flex-col overflow-hidden'; + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; - const nameSpan = document.createElement('div'); - nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; - nameSpan.textContent = pageState.file.name; + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = pageState.file.name; - const metaSpan = document.createElement('div'); - metaSpan.className = 'text-xs text-gray-400'; - metaSpan.textContent = formatBytes(pageState.file.size); + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(pageState.file.size); - infoContainer.append(nameSpan, metaSpan); + infoContainer.append(nameSpan, metaSpan); - const removeBtn = document.createElement('button'); - removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; - removeBtn.innerHTML = ''; - removeBtn.onclick = function () { - resetState(); - }; + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = function () { + resetState(); + }; - fileDiv.append(infoContainer, removeBtn); - fileDisplayArea.appendChild(fileDiv); - createIcons({ icons }); + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + createIcons({ icons }); - if (toolOptions) toolOptions.classList.remove('hidden'); - } else { - if (toolOptions) toolOptions.classList.add('hidden'); - } + if (toolOptions) toolOptions.classList.remove('hidden'); + } else { + if (toolOptions) toolOptions.classList.add('hidden'); + } } function handleFileSelect(files: FileList | null) { - if (files && files.length > 0) { - const file = files[0]; - if (file.type === 'application/pdf' || file.name.toLowerCase().endsWith('.pdf')) { - pageState.file = file; - updateUI(); - } + if (files && files.length > 0) { + const file = files[0]; + if ( + file.type === 'application/pdf' || + file.name.toLowerCase().endsWith('.pdf') + ) { + pageState.file = file; + updateUI(); } + } } function populateLanguageList() { - const langList = document.getElementById('lang-list'); - if (!langList) return; + const langList = document.getElementById('lang-list'); + if (!langList) return; - langList.innerHTML = ''; + langList.innerHTML = ''; - Object.entries(tesseractLanguages).forEach(function ([code, name]) { - const label = document.createElement('label'); - label.className = 'flex items-center gap-2 p-2 rounded-md hover:bg-gray-700 cursor-pointer'; + Object.entries(tesseractLanguages).forEach(function ([code, name]) { + const label = document.createElement('label'); + label.className = + 'flex items-center gap-2 p-2 rounded-md hover:bg-gray-700 cursor-pointer'; - const checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.value = code; - checkbox.className = 'lang-checkbox w-4 h-4 rounded text-indigo-600 bg-gray-700 border-gray-600 focus:ring-indigo-500'; + const checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.value = code; + checkbox.className = + 'lang-checkbox w-4 h-4 rounded text-indigo-600 bg-gray-700 border-gray-600 focus:ring-indigo-500'; - label.append(checkbox); - label.append(document.createTextNode(' ' + name)); - langList.appendChild(label); - }); + label.append(checkbox); + label.append(document.createTextNode(' ' + name)); + langList.appendChild(label); + }); } document.addEventListener('DOMContentLoaded', function () { - const fileInput = document.getElementById('file-input') as HTMLInputElement; - const dropZone = document.getElementById('drop-zone'); - const processBtn = document.getElementById('process-btn') as HTMLButtonElement; - const backBtn = document.getElementById('back-to-tools'); - const langSearch = document.getElementById('lang-search') as HTMLInputElement; - const langList = document.getElementById('lang-list'); - const selectedLangsDisplay = document.getElementById('selected-langs-display'); - const presetSelect = document.getElementById('whitelist-preset') as HTMLSelectElement; - const whitelistInput = document.getElementById('ocr-whitelist') as HTMLInputElement; - const copyBtn = document.getElementById('copy-text-btn'); - const downloadTxtBtn = document.getElementById('download-txt-btn'); - const downloadPdfBtn = document.getElementById('download-searchable-pdf'); + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById( + 'process-btn' + ) as HTMLButtonElement; + const backBtn = document.getElementById('back-to-tools'); + const langSearch = document.getElementById('lang-search') as HTMLInputElement; + const langList = document.getElementById('lang-list'); + const selectedLangsDisplay = document.getElementById( + 'selected-langs-display' + ); + const presetSelect = document.getElementById( + 'whitelist-preset' + ) as HTMLSelectElement; + const whitelistInput = document.getElementById( + 'ocr-whitelist' + ) as HTMLInputElement; + const copyBtn = document.getElementById('copy-text-btn'); + const downloadTxtBtn = document.getElementById('download-txt-btn'); + const downloadPdfBtn = document.getElementById('download-searchable-pdf'); - populateLanguageList(); + populateLanguageList(); - if (backBtn) { - backBtn.addEventListener('click', function () { - window.location.href = import.meta.env.BASE_URL; - }); - } + if (backBtn) { + backBtn.addEventListener('click', function () { + window.location.href = import.meta.env.BASE_URL; + }); + } - if (fileInput && dropZone) { - fileInput.addEventListener('change', function (e) { - handleFileSelect((e.target as HTMLInputElement).files); - }); - - dropZone.addEventListener('dragover', function (e) { - e.preventDefault(); - dropZone.classList.add('bg-gray-700'); - }); - - dropZone.addEventListener('dragleave', function (e) { - e.preventDefault(); - dropZone.classList.remove('bg-gray-700'); - }); - - dropZone.addEventListener('drop', function (e) { - e.preventDefault(); - dropZone.classList.remove('bg-gray-700'); - const files = e.dataTransfer?.files; - if (files && files.length > 0) { - const pdfFiles = Array.from(files).filter(function (f) { - return f.type === 'application/pdf' || f.name.toLowerCase().endsWith('.pdf'); - }); - if (pdfFiles.length > 0) { - const dataTransfer = new DataTransfer(); - dataTransfer.items.add(pdfFiles[0]); - handleFileSelect(dataTransfer.files); - } - } - }); - - fileInput.addEventListener('click', function () { - fileInput.value = ''; - }); - } - - // Language search - if (langSearch && langList) { - langSearch.addEventListener('input', function () { - const searchTerm = langSearch.value.toLowerCase(); - langList.querySelectorAll('label').forEach(function (label) { - (label as HTMLElement).style.display = label.textContent?.toLowerCase().includes(searchTerm) ? '' : 'none'; - }); - }); - - langList.addEventListener('change', function () { - const selected = Array.from( - langList.querySelectorAll('.lang-checkbox:checked') - ).map(function (cb) { - return tesseractLanguages[(cb as HTMLInputElement).value as keyof typeof tesseractLanguages]; - }); - - if (selectedLangsDisplay) { - selectedLangsDisplay.textContent = selected.length > 0 ? selected.join(', ') : 'None'; - } - - if (processBtn) { - processBtn.disabled = selected.length === 0; - } - }); - } - - // Whitelist preset - if (presetSelect && whitelistInput) { - presetSelect.addEventListener('change', function () { - const preset = presetSelect.value; - if (preset && preset !== 'custom') { - whitelistInput.value = whitelistPresets[preset] || ''; - whitelistInput.disabled = true; - } else { - whitelistInput.disabled = false; - if (preset === '') { - whitelistInput.value = ''; - } - } - }); - } - - // Details toggle - document.querySelectorAll('details').forEach(function (details) { - details.addEventListener('toggle', function () { - const icon = details.querySelector('.details-icon') as HTMLElement; - if (icon) { - icon.style.transform = (details as HTMLDetailsElement).open ? 'rotate(180deg)' : 'rotate(0deg)'; - } - }); + if (fileInput && dropZone) { + fileInput.addEventListener('change', function (e) { + handleFileSelect((e.target as HTMLInputElement).files); }); - // Process button - if (processBtn) { - processBtn.addEventListener('click', runOCR); - } + dropZone.addEventListener('dragover', function (e) { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); - // Copy button - if (copyBtn) { - copyBtn.addEventListener('click', function () { - const textOutput = document.getElementById('ocr-text-output') as HTMLTextAreaElement; - if (textOutput) { - navigator.clipboard.writeText(textOutput.value).then(function () { - copyBtn.innerHTML = ''; - createIcons({ icons }); + dropZone.addEventListener('dragleave', function (e) { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); - setTimeout(function () { - copyBtn.innerHTML = ''; - createIcons({ icons }); - }, 2000); - }); - } + dropZone.addEventListener('drop', function (e) { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const files = e.dataTransfer?.files; + if (files && files.length > 0) { + const pdfFiles = Array.from(files).filter(function (f) { + return ( + f.type === 'application/pdf' || + f.name.toLowerCase().endsWith('.pdf') + ); }); - } + if (pdfFiles.length > 0) { + const dataTransfer = new DataTransfer(); + dataTransfer.items.add(pdfFiles[0]); + handleFileSelect(dataTransfer.files); + } + } + }); - // Download txt - if (downloadTxtBtn) { - downloadTxtBtn.addEventListener('click', function () { - const textOutput = document.getElementById('ocr-text-output') as HTMLTextAreaElement; - if (textOutput) { - const blob = new Blob([textOutput.value], { type: 'text/plain' }); - downloadFile(blob, 'ocr-text.txt'); - } - }); - } + fileInput.addEventListener('click', function () { + fileInput.value = ''; + }); + } - // Download PDF - if (downloadPdfBtn) { - downloadPdfBtn.addEventListener('click', function () { - if (pageState.searchablePdfBytes) { - downloadFile( - new Blob([new Uint8Array(pageState.searchablePdfBytes)], { type: 'application/pdf' }), - 'searchable.pdf' - ); - } + // Language search + if (langSearch && langList) { + langSearch.addEventListener('input', function () { + const searchTerm = langSearch.value.toLowerCase(); + langList.querySelectorAll('label').forEach(function (label) { + (label as HTMLElement).style.display = label.textContent + ?.toLowerCase() + .includes(searchTerm) + ? '' + : 'none'; + }); + }); + + langList.addEventListener('change', function () { + const selected = Array.from( + langList.querySelectorAll('.lang-checkbox:checked') + ).map(function (cb) { + return tesseractLanguages[ + (cb as HTMLInputElement).value as keyof typeof tesseractLanguages + ]; + }); + + if (selectedLangsDisplay) { + selectedLangsDisplay.textContent = + selected.length > 0 ? selected.join(', ') : 'None'; + } + + if (processBtn) { + processBtn.disabled = selected.length === 0; + } + }); + } + + // Whitelist preset + if (presetSelect && whitelistInput) { + presetSelect.addEventListener('change', function () { + const preset = presetSelect.value; + if (preset && preset !== 'custom') { + whitelistInput.value = whitelistPresets[preset] || ''; + whitelistInput.disabled = true; + } else { + whitelistInput.disabled = false; + if (preset === '') { + whitelistInput.value = ''; + } + } + }); + } + + // Details toggle + document.querySelectorAll('details').forEach(function (details) { + details.addEventListener('toggle', function () { + const icon = details.querySelector('.details-icon') as HTMLElement; + if (icon) { + icon.style.transform = (details as HTMLDetailsElement).open + ? 'rotate(180deg)' + : 'rotate(0deg)'; + } + }); + }); + + // Process button + if (processBtn) { + processBtn.addEventListener('click', runOCR); + } + + // Copy button + if (copyBtn) { + copyBtn.addEventListener('click', function () { + const textOutput = document.getElementById( + 'ocr-text-output' + ) as HTMLTextAreaElement; + if (textOutput) { + navigator.clipboard.writeText(textOutput.value).then(function () { + copyBtn.innerHTML = + ''; + createIcons({ icons }); + + setTimeout(function () { + copyBtn.innerHTML = + ''; + createIcons({ icons }); + }, 2000); }); - } + } + }); + } + + // Download txt + if (downloadTxtBtn) { + downloadTxtBtn.addEventListener('click', function () { + const textOutput = document.getElementById( + 'ocr-text-output' + ) as HTMLTextAreaElement; + if (textOutput) { + const blob = new Blob([textOutput.value], { type: 'text/plain' }); + downloadFile(blob, 'ocr-text.txt'); + } + }); + } + + // Download PDF + if (downloadPdfBtn) { + downloadPdfBtn.addEventListener('click', function () { + if (pageState.searchablePdfBytes) { + downloadFile( + new Blob([new Uint8Array(pageState.searchablePdfBytes)], { + type: 'application/pdf', + }), + 'searchable.pdf' + ); + } + }); + } }); diff --git a/src/js/logic/odg-to-pdf-page.ts b/src/js/logic/odg-to-pdf-page.ts new file mode 100644 index 0000000..1d874d4 --- /dev/null +++ b/src/js/logic/odg-to-pdf-page.ts @@ -0,0 +1,189 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { + downloadFile, + formatBytes, +} from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { getLibreOfficeConverter, type LoadProgress } from '../utils/libreoffice-loader.js'; + +const ACCEPTED_EXTENSIONS = ['.odg']; +const FILETYPE_NAME = 'ODG'; + +document.addEventListener('DOMContentLoaded', () => { + state.files = []; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const convertOptions = document.getElementById('convert-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const processBtn = document.getElementById('process-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!convertOptions) return; + + if (state.files.length > 0) { + if (fileDisplayArea) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + } + if (fileControls) fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + } else { + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + if (fileControls) fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + updateUI(); + }; + + const convert = async () => { + if (state.files.length === 0) { + showAlert('No Files', `Please select at least one ${FILETYPE_NAME} file.`); + return; + } + + try { + const converter = getLibreOfficeConverter(); + + showLoader('Loading engine...'); + await converter.initialize((progress: LoadProgress) => { + showLoader(progress.message, progress.percent); + }); + + if (state.files.length === 1) { + const file = state.files[0]; + showLoader(`Converting ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + downloadFile(pdfBlob, `${baseName}.pdf`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${file.name} to PDF.`, 'success', () => resetState()); + } else { + showLoader('Converting multiple files...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + zip.file(`${baseName}.pdf`, pdfBlob); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, `${FILETYPE_NAME.toLowerCase()}-to-pdf.zip`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${state.files.length} files to PDF.`, 'success', () => resetState()); + } + } catch (err) { + hideLoader(); + const message = err instanceof Error ? err.message : 'Unknown error'; + console.error(`[${FILETYPE_NAME}ToPDF] Error:`, err); + showAlert('Error', `An error occurred during conversion. Error: ${message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(file => { + const ext = '.' + file.name.split('.').pop()?.toLowerCase(); + return ACCEPTED_EXTENSIONS.includes(ext); + }); + if (validFiles.length > 0) { + state.files = [...state.files, ...validFiles]; + updateUI(); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => fileInput.click()); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', resetState); + } + + if (processBtn) { + processBtn.addEventListener('click', convert); + } + + updateUI(); +}); diff --git a/src/js/logic/odp-to-pdf-page.ts b/src/js/logic/odp-to-pdf-page.ts new file mode 100644 index 0000000..b9c7cd2 --- /dev/null +++ b/src/js/logic/odp-to-pdf-page.ts @@ -0,0 +1,189 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { + downloadFile, + formatBytes, +} from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { getLibreOfficeConverter, type LoadProgress } from '../utils/libreoffice-loader.js'; + +const ACCEPTED_EXTENSIONS = ['.odp']; +const FILETYPE_NAME = 'ODP'; + +document.addEventListener('DOMContentLoaded', () => { + state.files = []; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const convertOptions = document.getElementById('convert-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const processBtn = document.getElementById('process-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!convertOptions) return; + + if (state.files.length > 0) { + if (fileDisplayArea) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + } + if (fileControls) fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + } else { + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + if (fileControls) fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + updateUI(); + }; + + const convert = async () => { + if (state.files.length === 0) { + showAlert('No Files', `Please select at least one ${FILETYPE_NAME} file.`); + return; + } + + try { + const converter = getLibreOfficeConverter(); + + showLoader('Loading engine...'); + await converter.initialize((progress: LoadProgress) => { + showLoader(progress.message, progress.percent); + }); + + if (state.files.length === 1) { + const file = state.files[0]; + showLoader(`Converting ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + downloadFile(pdfBlob, `${baseName}.pdf`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${file.name} to PDF.`, 'success', () => resetState()); + } else { + showLoader('Converting multiple files...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + zip.file(`${baseName}.pdf`, pdfBlob); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, `${FILETYPE_NAME.toLowerCase()}-to-pdf.zip`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${state.files.length} files to PDF.`, 'success', () => resetState()); + } + } catch (err) { + hideLoader(); + const message = err instanceof Error ? err.message : 'Unknown error'; + console.error(`[${FILETYPE_NAME}ToPDF] Error:`, err); + showAlert('Error', `An error occurred during conversion. Error: ${message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(file => { + const ext = '.' + file.name.split('.').pop()?.toLowerCase(); + return ACCEPTED_EXTENSIONS.includes(ext); + }); + if (validFiles.length > 0) { + state.files = [...state.files, ...validFiles]; + updateUI(); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => fileInput.click()); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', resetState); + } + + if (processBtn) { + processBtn.addEventListener('click', convert); + } + + updateUI(); +}); diff --git a/src/js/logic/ods-to-pdf-page.ts b/src/js/logic/ods-to-pdf-page.ts new file mode 100644 index 0000000..24343ec --- /dev/null +++ b/src/js/logic/ods-to-pdf-page.ts @@ -0,0 +1,189 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { + downloadFile, + formatBytes, +} from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { getLibreOfficeConverter, type LoadProgress } from '../utils/libreoffice-loader.js'; + +const ACCEPTED_EXTENSIONS = ['.ods']; +const FILETYPE_NAME = 'ODS'; + +document.addEventListener('DOMContentLoaded', () => { + state.files = []; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const convertOptions = document.getElementById('convert-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const processBtn = document.getElementById('process-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!convertOptions) return; + + if (state.files.length > 0) { + if (fileDisplayArea) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + } + if (fileControls) fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + } else { + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + if (fileControls) fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + updateUI(); + }; + + const convert = async () => { + if (state.files.length === 0) { + showAlert('No Files', `Please select at least one ${FILETYPE_NAME} file.`); + return; + } + + try { + const converter = getLibreOfficeConverter(); + + showLoader('Loading engine...'); + await converter.initialize((progress: LoadProgress) => { + showLoader(progress.message, progress.percent); + }); + + if (state.files.length === 1) { + const file = state.files[0]; + showLoader(`Converting ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + downloadFile(pdfBlob, `${baseName}.pdf`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${file.name} to PDF.`, 'success', () => resetState()); + } else { + showLoader('Converting multiple files...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + zip.file(`${baseName}.pdf`, pdfBlob); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, `${FILETYPE_NAME.toLowerCase()}-to-pdf.zip`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${state.files.length} files to PDF.`, 'success', () => resetState()); + } + } catch (err) { + hideLoader(); + const message = err instanceof Error ? err.message : 'Unknown error'; + console.error(`[${FILETYPE_NAME}ToPDF] Error:`, err); + showAlert('Error', `An error occurred during conversion. Error: ${message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(file => { + const ext = '.' + file.name.split('.').pop()?.toLowerCase(); + return ACCEPTED_EXTENSIONS.includes(ext); + }); + if (validFiles.length > 0) { + state.files = [...state.files, ...validFiles]; + updateUI(); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => fileInput.click()); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', resetState); + } + + if (processBtn) { + processBtn.addEventListener('click', convert); + } + + updateUI(); +}); diff --git a/src/js/logic/odt-to-pdf-page.ts b/src/js/logic/odt-to-pdf-page.ts new file mode 100644 index 0000000..43ff895 --- /dev/null +++ b/src/js/logic/odt-to-pdf-page.ts @@ -0,0 +1,215 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { + downloadFile, + readFileAsArrayBuffer, + formatBytes, +} from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { getLibreOfficeConverter, type LoadProgress } from '../utils/libreoffice-loader.js'; + +document.addEventListener('DOMContentLoaded', () => { + state.files = []; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const convertOptions = document.getElementById('convert-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const processBtn = document.getElementById('process-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!convertOptions) return; + + if (state.files.length > 0) { + if (fileDisplayArea) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + } + if (fileControls) fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + } else { + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + if (fileControls) fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + state.pdfDoc = null; + updateUI(); + }; + + const convertToPdf = async () => { + try { + if (state.files.length === 0) { + showAlert('No Files', 'Please select at least one ODT file.'); + hideLoader(); + return; + } + + const converter = getLibreOfficeConverter(); + + // Initialize LibreOffice if not already done + await converter.initialize((progress: LoadProgress) => { + showLoader(progress.message, progress.percent); + }); + + if (state.files.length === 1) { + const originalFile = state.files[0]; + + showLoader('Processing...'); + + const pdfBlob = await converter.convertToPdf(originalFile); + + const fileName = originalFile.name.replace(/\.odt$/i, '') + '.pdf'; + + downloadFile(pdfBlob, fileName); + + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${originalFile.name} to PDF.`, + 'success', + () => resetState() + ); + } else { + showLoader('Processing...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.odt$/i, ''); + const pdfBuffer = await pdfBlob.arrayBuffer(); + zip.file(`${baseName}.pdf`, pdfBuffer); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + + downloadFile(zipBlob, 'odt-converted.zip'); + + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${state.files.length} ODT file(s) to PDF.`, + 'success', + () => resetState() + ); + } + } catch (e: any) { + hideLoader(); + showAlert( + 'Error', + `An error occurred during conversion. Error: ${e.message}` + ); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + state.files = [...state.files, ...Array.from(files)]; + updateUI(); + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const files = e.dataTransfer?.files; + if (files && files.length > 0) { + const odtFiles = Array.from(files).filter(f => f.name.toLowerCase().endsWith('.odt') || f.type === 'application/vnd.oasis.opendocument.text'); + if (odtFiles.length > 0) { + const dataTransfer = new DataTransfer(); + odtFiles.forEach(f => dataTransfer.items.add(f)); + handleFileSelect(dataTransfer.files); + } + } + }); + + // Clear value on click to allow re-selecting the same file + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => { + fileInput.click(); + }); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', () => { + resetState(); + }); + } + + if (processBtn) { + processBtn.addEventListener('click', convertToPdf); + } + + updateUI(); +}); diff --git a/src/js/logic/page-dimensions-page.ts b/src/js/logic/page-dimensions-page.ts index 9f1c9d0..71458f4 100644 --- a/src/js/logic/page-dimensions-page.ts +++ b/src/js/logic/page-dimensions-page.ts @@ -2,13 +2,9 @@ import { showAlert } from '../ui.js'; import { formatBytes, getStandardPageName, convertPoints } from '../utils/helpers.js'; import { PDFDocument } from 'pdf-lib'; import { icons, createIcons } from 'lucide'; +import { PageDimensionsState } from '@/types'; -interface PageState { - file: File | null; - pdfDoc: PDFDocument | null; -} - -const pageState: PageState = { +const pageState: PageDimensionsState = { file: null, pdfDoc: null, }; diff --git a/src/js/logic/page-numbers-page.ts b/src/js/logic/page-numbers-page.ts index ae387fe..12f3d53 100644 --- a/src/js/logic/page-numbers-page.ts +++ b/src/js/logic/page-numbers-page.ts @@ -162,7 +162,7 @@ async function addPageNumbers() { const xOffset = bounds.x || 0; const yOffset = bounds.y || 0; - let pageNumText = format === 'page_x_of_y' ? `${i + 1} / ${totalPages}` : `${i + 1}`; + const pageNumText = format === 'page_x_of_y' ? `${i + 1} / ${totalPages}` : `${i + 1}`; const textWidth = helveticaFont.widthOfTextAtSize(pageNumText, fontSize); const textHeight = fontSize; diff --git a/src/js/logic/pages-to-pdf-page.ts b/src/js/logic/pages-to-pdf-page.ts new file mode 100644 index 0000000..506eced --- /dev/null +++ b/src/js/logic/pages-to-pdf-page.ts @@ -0,0 +1,188 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { + downloadFile, + formatBytes, +} from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { getLibreOfficeConverter, type LoadProgress } from '../utils/libreoffice-loader.js'; + +const ACCEPTED_EXTENSIONS = ['.pages']; +const FILETYPE_NAME = 'Pages'; + +document.addEventListener('DOMContentLoaded', () => { + state.files = []; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const convertOptions = document.getElementById('convert-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const processBtn = document.getElementById('process-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!convertOptions) return; + + if (state.files.length > 0) { + if (fileDisplayArea) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + } + if (fileControls) fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + } else { + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + if (fileControls) fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + updateUI(); + }; + + const convert = async () => { + if (state.files.length === 0) { + showAlert('No Files', `Please select at least one ${FILETYPE_NAME} file.`); + return; + } + + try { + const converter = getLibreOfficeConverter(); + + showLoader('Loading engine...'); + await converter.initialize((progress: LoadProgress) => { + showLoader(progress.message, progress.percent); + }); + + if (state.files.length === 1) { + const file = state.files[0]; + showLoader(`Converting ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + downloadFile(pdfBlob, `${baseName}.pdf`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${file.name} to PDF.`, 'success', () => resetState()); + } else { + showLoader('Converting multiple files...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + zip.file(`${baseName}.pdf`, pdfBlob); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, `${FILETYPE_NAME.toLowerCase()}-to-pdf.zip`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${state.files.length} files to PDF.`, 'success', () => resetState()); + } + } catch (e: any) { + hideLoader(); + console.error(`[${FILETYPE_NAME}ToPDF] Error:`, e); + showAlert('Error', `An error occurred during conversion. Error: ${e.message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(file => { + const ext = '.' + file.name.split('.').pop()?.toLowerCase(); + return ACCEPTED_EXTENSIONS.includes(ext); + }); + if (validFiles.length > 0) { + state.files = [...state.files, ...validFiles]; + updateUI(); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => fileInput.click()); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', resetState); + } + + if (processBtn) { + processBtn.addEventListener('click', convert); + } + + updateUI(); +}); diff --git a/src/js/logic/pdf-booklet-page.ts b/src/js/logic/pdf-booklet-page.ts new file mode 100644 index 0000000..489ba45 --- /dev/null +++ b/src/js/logic/pdf-booklet-page.ts @@ -0,0 +1,517 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; +import { createIcons, icons } from 'lucide'; +import { PDFDocument as PDFLibDocument, degrees, PageSizes } from 'pdf-lib'; +import * as pdfjsLib from 'pdfjs-dist'; + +pdfjsLib.GlobalWorkerOptions.workerSrc = new URL( + 'pdfjs-dist/build/pdf.worker.mjs', + import.meta.url +).toString(); + +interface BookletState { + file: File | null; + pdfDoc: PDFLibDocument | null; + pdfBytes: Uint8Array | null; + pdfjsDoc: pdfjsLib.PDFDocumentProxy | null; +} + +const pageState: BookletState = { + file: null, + pdfDoc: null, + pdfBytes: null, + pdfjsDoc: null, +}; + +function resetState() { + pageState.file = null; + pageState.pdfDoc = null; + pageState.pdfBytes = null; + pageState.pdfjsDoc = null; + + const fileDisplayArea = document.getElementById('file-display-area'); + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + + const toolOptions = document.getElementById('tool-options'); + if (toolOptions) toolOptions.classList.add('hidden'); + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + if (fileInput) fileInput.value = ''; + + const previewArea = document.getElementById('booklet-preview'); + if (previewArea) previewArea.innerHTML = '

Upload a PDF and click "Generate Preview" to see the booklet layout

'; + + const downloadBtn = document.getElementById('download-btn') as HTMLButtonElement; + if (downloadBtn) downloadBtn.disabled = true; +} + +async function updateUI() { + const fileDisplayArea = document.getElementById('file-display-area'); + const toolOptions = document.getElementById('tool-options'); + + if (!fileDisplayArea) return; + + fileDisplayArea.innerHTML = ''; + + if (pageState.file) { + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = pageState.file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = `${formatBytes(pageState.file.size)} • Loading...`; + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = function () { + resetState(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + createIcons({ icons }); + + try { + showLoader('Loading PDF...'); + const arrayBuffer = await pageState.file.arrayBuffer(); + pageState.pdfBytes = new Uint8Array(arrayBuffer); + + pageState.pdfDoc = await PDFLibDocument.load(pageState.pdfBytes, { + ignoreEncryption: true, + throwOnInvalidObject: false + }); + + pageState.pdfjsDoc = await pdfjsLib.getDocument({ data: pageState.pdfBytes.slice() }).promise; + + hideLoader(); + + const pageCount = pageState.pdfDoc.getPageCount(); + metaSpan.textContent = `${formatBytes(pageState.file.size)} • ${pageCount} pages`; + + if (toolOptions) toolOptions.classList.remove('hidden'); + + const previewBtn = document.getElementById('preview-btn') as HTMLButtonElement; + if (previewBtn) previewBtn.disabled = false; + } catch (error) { + console.error('Error loading PDF:', error); + hideLoader(); + showAlert('Error', 'Failed to load PDF file.'); + resetState(); + } + } else { + if (toolOptions) toolOptions.classList.add('hidden'); + } +} + +function getGridDimensions(): { rows: number; cols: number } { + const gridMode = (document.querySelector('input[name="grid-mode"]:checked') as HTMLInputElement)?.value || '1x2'; + switch (gridMode) { + case '1x2': return { rows: 1, cols: 2 }; + case '2x2': return { rows: 2, cols: 2 }; + case '2x4': return { rows: 2, cols: 4 }; + case '4x4': return { rows: 4, cols: 4 }; + default: return { rows: 1, cols: 2 }; + } +} + +function getOrientation(isBookletMode: boolean): 'portrait' | 'landscape' { + const orientationValue = (document.querySelector('input[name="orientation"]:checked') as HTMLInputElement)?.value || 'auto'; + if (orientationValue === 'portrait') return 'portrait'; + if (orientationValue === 'landscape') return 'landscape'; + return isBookletMode ? 'landscape' : 'portrait'; +} + +function getSheetDimensions(isBookletMode: boolean): { width: number; height: number } { + const paperSizeKey = (document.getElementById('paper-size') as HTMLSelectElement).value as keyof typeof PageSizes; + const pageDims = PageSizes[paperSizeKey] || PageSizes.Letter; + const orientation = getOrientation(isBookletMode); + if (orientation === 'landscape') { + return { width: pageDims[1], height: pageDims[0] }; + } + return { width: pageDims[0], height: pageDims[1] }; +} + +async function generatePreview() { + if (!pageState.pdfDoc || !pageState.pdfjsDoc) { + showAlert('Error', 'Please load a PDF first.'); + return; + } + + const previewArea = document.getElementById('booklet-preview')!; + const totalPages = pageState.pdfDoc.getPageCount(); + const { rows, cols } = getGridDimensions(); + const pagesPerSheet = rows * cols; + const isBookletMode = rows === 1 && cols === 2; + + let numSheets: number; + if (isBookletMode) { + const sheetsNeeded = Math.ceil(totalPages / 4); + numSheets = sheetsNeeded * 2; + } else { + numSheets = Math.ceil(totalPages / pagesPerSheet); + } + + const { width: sheetWidth, height: sheetHeight } = getSheetDimensions(isBookletMode); + + // Get container width to make canvas fill it + const previewContainer = document.getElementById('booklet-preview')!; + const containerWidth = previewContainer.clientWidth - 32; // account for padding + const aspectRatio = sheetWidth / sheetHeight; + const canvasWidth = containerWidth; + const canvasHeight = containerWidth / aspectRatio; + + previewArea.innerHTML = '

Generating preview...

'; + + const totalRounded = isBookletMode ? Math.ceil(totalPages / 4) * 4 : totalPages; + const rotationMode = (document.querySelector('input[name="rotation"]:checked') as HTMLInputElement)?.value || 'none'; + + const pageThumbnails: Map = new Map(); + const thumbnailScale = 0.3; + + for (let i = 1; i <= totalPages; i++) { + try { + const page = await pageState.pdfjsDoc.getPage(i); + const viewport = page.getViewport({ scale: thumbnailScale }); + + const offscreen = new OffscreenCanvas(viewport.width, viewport.height); + const ctx = offscreen.getContext('2d')!; + + await page.render({ + canvasContext: ctx as any, + viewport: viewport, + canvas: offscreen as any, + }).promise; + + const bitmap = await createImageBitmap(offscreen); + pageThumbnails.set(i, bitmap); + } catch (e) { + console.error(`Failed to render page ${i}:`, e); + } + } + + previewArea.innerHTML = `

${totalPages} pages → ${numSheets} output sheets

`; + + for (let sheetIndex = 0; sheetIndex < numSheets; sheetIndex++) { + const canvas = document.createElement('canvas'); + canvas.width = canvasWidth; + canvas.height = canvasHeight; + canvas.className = 'border border-gray-600 rounded-lg mb-4'; + + const ctx = canvas.getContext('2d')!; + + const isFront = sheetIndex % 2 === 0; + ctx.fillStyle = isFront ? '#1f2937' : '#1a2e1a'; + ctx.fillRect(0, 0, canvasWidth, canvasHeight); + + ctx.strokeStyle = '#4b5563'; + ctx.lineWidth = 1; + ctx.strokeRect(0, 0, canvasWidth, canvasHeight); + + const cellWidth = canvasWidth / cols; + const cellHeight = canvasHeight / rows; + const padding = 4; + + ctx.strokeStyle = '#374151'; + ctx.lineWidth = 1; + ctx.setLineDash([2, 2]); + for (let c = 1; c < cols; c++) { + ctx.beginPath(); + ctx.moveTo(c * cellWidth, 0); + ctx.lineTo(c * cellWidth, canvasHeight); + ctx.stroke(); + } + for (let r = 1; r < rows; r++) { + ctx.beginPath(); + ctx.moveTo(0, r * cellHeight); + ctx.lineTo(canvasWidth, r * cellHeight); + ctx.stroke(); + } + ctx.setLineDash([]); + + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + const slotIndex = r * cols + c; + let pageNumber: number; + + if (isBookletMode) { + const physicalSheet = Math.floor(sheetIndex / 2); + const isFrontSide = sheetIndex % 2 === 0; + if (isFrontSide) { + pageNumber = c === 0 ? totalRounded - 2 * physicalSheet : 2 * physicalSheet + 1; + } else { + pageNumber = c === 0 ? 2 * physicalSheet + 2 : totalRounded - 2 * physicalSheet - 1; + } + } else { + pageNumber = sheetIndex * pagesPerSheet + slotIndex + 1; + } + + const x = c * cellWidth + padding; + const y = r * cellHeight + padding; + const slotWidth = cellWidth - padding * 2; + const slotHeight = cellHeight - padding * 2; + + const exists = pageNumber >= 1 && pageNumber <= totalPages; + + if (exists) { + const thumbnail = pageThumbnails.get(pageNumber); + if (thumbnail) { + let rotation = 0; + if (rotationMode === '90cw') rotation = 90; + else if (rotationMode === '90ccw') rotation = -90; + else if (rotationMode === 'alternate') rotation = (pageNumber % 2 === 1) ? 90 : -90; + + const isRotated = rotation !== 0; + const srcWidth = isRotated ? thumbnail.height : thumbnail.width; + const srcHeight = isRotated ? thumbnail.width : thumbnail.height; + const scale = Math.min(slotWidth / srcWidth, slotHeight / srcHeight); + const drawWidth = srcWidth * scale; + const drawHeight = srcHeight * scale; + const drawX = x + (slotWidth - drawWidth) / 2; + const drawY = y + (slotHeight - drawHeight) / 2; + + ctx.save(); + if (rotation !== 0) { + const centerX = drawX + drawWidth / 2; + const centerY = drawY + drawHeight / 2; + ctx.translate(centerX, centerY); + ctx.rotate((rotation * Math.PI) / 180); + ctx.drawImage(thumbnail, -drawHeight / 2, -drawWidth / 2, drawHeight, drawWidth); + } else { + ctx.drawImage(thumbnail, drawX, drawY, drawWidth, drawHeight); + } + ctx.restore(); + + ctx.strokeStyle = '#6b7280'; + ctx.lineWidth = 1; + ctx.strokeRect(drawX, drawY, drawWidth, drawHeight); + + ctx.fillStyle = 'rgba(255, 255, 255, 0.8)'; + ctx.font = 'bold 10px sans-serif'; + ctx.textAlign = 'center'; + ctx.fillText(`${pageNumber}`, x + slotWidth / 2, y + slotHeight - 4); + } + } else { + ctx.fillStyle = '#374151'; + ctx.fillRect(x, y, slotWidth, slotHeight); + ctx.strokeStyle = '#4b5563'; + ctx.lineWidth = 1; + ctx.strokeRect(x, y, slotWidth, slotHeight); + + ctx.fillStyle = '#6b7280'; + ctx.font = '10px sans-serif'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText('(blank)', x + slotWidth / 2, y + slotHeight / 2); + } + } + } + + ctx.fillStyle = '#9ca3af'; + ctx.font = 'bold 10px sans-serif'; + ctx.textAlign = 'right'; + ctx.textBaseline = 'top'; + const sideLabel = isBookletMode ? (isFront ? 'Front' : 'Back') : ''; + ctx.fillText(`Sheet ${Math.floor(sheetIndex / (isBookletMode ? 2 : 1)) + 1} ${sideLabel}`, canvasWidth - 6, 4); + + previewArea.appendChild(canvas); + } + + pageThumbnails.forEach(bitmap => bitmap.close()); + + const downloadBtn = document.getElementById('download-btn') as HTMLButtonElement; + downloadBtn.disabled = false; +} + +function applyRotation(doc: PDFLibDocument, mode: string) { + const pages = doc.getPages(); + pages.forEach((page, index) => { + let rotation = 0; + switch (mode) { + case '90cw': rotation = 90; break; + case '90ccw': rotation = -90; break; + case 'alternate': rotation = (index % 2 === 0) ? 90 : -90; break; + default: rotation = 0; + } + if (rotation !== 0) { + page.setRotation(degrees(page.getRotation().angle + rotation)); + } + }); +} + +async function createBooklet() { + if (!pageState.pdfBytes) { + showAlert('Error', 'Please load a PDF first.'); + return; + } + + showLoader('Creating Booklet...'); + + try { + const sourceDoc = await PDFLibDocument.load(pageState.pdfBytes.slice()); + const rotationMode = (document.querySelector('input[name="rotation"]:checked') as HTMLInputElement)?.value || 'none'; + applyRotation(sourceDoc, rotationMode); + + const totalPages = sourceDoc.getPageCount(); + const { rows, cols } = getGridDimensions(); + const pagesPerSheet = rows * cols; + const isBookletMode = rows === 1 && cols === 2; + + const { width: sheetWidth, height: sheetHeight } = getSheetDimensions(isBookletMode); + + const outputDoc = await PDFLibDocument.create(); + + let numSheets: number; + let totalRounded: number; + if (isBookletMode) { + totalRounded = Math.ceil(totalPages / 4) * 4; + numSheets = Math.ceil(totalPages / 4) * 2; + } else { + totalRounded = totalPages; + numSheets = Math.ceil(totalPages / pagesPerSheet); + } + + const cellWidth = sheetWidth / cols; + const cellHeight = sheetHeight / rows; + const padding = 10; + + for (let sheetIndex = 0; sheetIndex < numSheets; sheetIndex++) { + const outputPage = outputDoc.addPage([sheetWidth, sheetHeight]); + + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + const slotIndex = r * cols + c; + let pageNumber: number; + + if (isBookletMode) { + const physicalSheet = Math.floor(sheetIndex / 2); + const isFrontSide = sheetIndex % 2 === 0; + if (isFrontSide) { + pageNumber = c === 0 ? totalRounded - 2 * physicalSheet : 2 * physicalSheet + 1; + } else { + pageNumber = c === 0 ? 2 * physicalSheet + 2 : totalRounded - 2 * physicalSheet - 1; + } + } else { + pageNumber = sheetIndex * pagesPerSheet + slotIndex + 1; + } + + if (pageNumber >= 1 && pageNumber <= totalPages) { + const [embeddedPage] = await outputDoc.embedPdf(sourceDoc, [pageNumber - 1]); + const { width: srcW, height: srcH } = embeddedPage; + + const availableWidth = cellWidth - padding * 2; + const availableHeight = cellHeight - padding * 2; + const scale = Math.min(availableWidth / srcW, availableHeight / srcH); + + const scaledWidth = srcW * scale; + const scaledHeight = srcH * scale; + + const x = c * cellWidth + padding + (availableWidth - scaledWidth) / 2; + const y = sheetHeight - (r + 1) * cellHeight + padding + (availableHeight - scaledHeight) / 2; + + outputPage.drawPage(embeddedPage, { + x, + y, + width: scaledWidth, + height: scaledHeight, + }); + } + } + } + } + + const pdfBytes = await outputDoc.save(); + const originalName = pageState.file?.name.replace(/\.pdf$/i, '') || 'document'; + + downloadFile( + new Blob([new Uint8Array(pdfBytes)], { type: 'application/pdf' }), + `${originalName}_booklet.pdf` + ); + + showAlert('Success', `Booklet created with ${numSheets} sheets!`, 'success', function () { + resetState(); + }); + } catch (e) { + console.error(e); + showAlert('Error', 'An error occurred while creating the booklet.'); + } finally { + hideLoader(); + } +} + +function handleFileSelect(files: FileList | null) { + if (files && files.length > 0) { + const file = files[0]; + if (file.type === 'application/pdf' || file.name.toLowerCase().endsWith('.pdf')) { + pageState.file = file; + updateUI(); + } + } +} + +document.addEventListener('DOMContentLoaded', function () { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const previewBtn = document.getElementById('preview-btn'); + const downloadBtn = document.getElementById('download-btn'); + const backBtn = document.getElementById('back-to-tools'); + + if (backBtn) { + backBtn.addEventListener('click', function () { + window.location.href = import.meta.env.BASE_URL; + }); + } + + if (fileInput && dropZone) { + fileInput.addEventListener('change', function (e) { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', function (e) { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', function (e) { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', function (e) { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const files = e.dataTransfer?.files; + if (files && files.length > 0) { + const pdfFiles = Array.from(files).filter(function (f) { + return f.type === 'application/pdf' || f.name.toLowerCase().endsWith('.pdf'); + }); + if (pdfFiles.length > 0) { + const dataTransfer = new DataTransfer(); + dataTransfer.items.add(pdfFiles[0]); + handleFileSelect(dataTransfer.files); + } + } + }); + + fileInput.addEventListener('click', function () { + fileInput.value = ''; + }); + } + + if (previewBtn) { + previewBtn.addEventListener('click', generatePreview); + } + + if (downloadBtn) { + downloadBtn.addEventListener('click', createBooklet); + } +}); diff --git a/src/js/logic/pdf-layers-page.ts b/src/js/logic/pdf-layers-page.ts new file mode 100644 index 0000000..2975e7a --- /dev/null +++ b/src/js/logic/pdf-layers-page.ts @@ -0,0 +1,416 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, readFileAsArrayBuffer, formatBytes, getPDFDocument } from '../utils/helpers.js'; +import { createIcons, icons } from 'lucide'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +const pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); + +interface LayerData { + number: number; + xref: number; + text: string; + on: boolean; + locked: boolean; + depth: number; + parentXref: number; + displayOrder: number; +}; + +let currentFile: File | null = null; +let currentDoc: any = null; +const layersMap = new Map(); +let nextDisplayOrder = 0; + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const processBtnContainer = document.getElementById('process-btn-container'); + const fileDisplayArea = document.getElementById('file-display-area'); + const layersContainer = document.getElementById('layers-container'); + const layersList = document.getElementById('layers-list'); + const backBtn = document.getElementById('back-to-tools'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!fileDisplayArea || !processBtnContainer || !processBtn) return; + + if (currentFile) { + fileDisplayArea.innerHTML = ''; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = currentFile.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = `${formatBytes(currentFile.size)} • Loading pages...`; + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + resetState(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + + try { + const arrayBuffer = await readFileAsArrayBuffer(currentFile); + const pdfDoc = await getPDFDocument({ data: arrayBuffer }).promise; + metaSpan.textContent = `${formatBytes(currentFile.size)} • ${pdfDoc.numPages} pages`; + } catch (error) { + console.error('Error loading PDF:', error); + metaSpan.textContent = `${formatBytes(currentFile.size)} • Could not load page count`; + } + + createIcons({ icons }); + processBtnContainer.classList.remove('hidden'); + (processBtn as HTMLButtonElement).disabled = false; + } else { + fileDisplayArea.innerHTML = ''; + processBtnContainer.classList.add('hidden'); + (processBtn as HTMLButtonElement).disabled = true; + } + }; + + const resetState = () => { + currentFile = null; + currentDoc = null; + layersMap.clear(); + nextDisplayOrder = 0; + + if (dropZone) dropZone.style.display = 'flex'; + if (layersContainer) layersContainer.classList.add('hidden'); + updateUI(); + }; + + const promptForInput = (title: string, message: string, defaultValue: string = ''): Promise => { + return new Promise((resolve) => { + const modal = document.getElementById('input-modal'); + const titleEl = document.getElementById('input-title'); + const messageEl = document.getElementById('input-message'); + const inputEl = document.getElementById('input-value') as HTMLInputElement; + const confirmBtn = document.getElementById('input-confirm'); + const cancelBtn = document.getElementById('input-cancel'); + + if (!modal || !titleEl || !messageEl || !inputEl || !confirmBtn || !cancelBtn) { + console.error('Input modal elements not found'); + resolve(null); + return; + } + + titleEl.textContent = title; + messageEl.textContent = message; + inputEl.value = defaultValue; + + const closeModal = () => { + modal.classList.add('hidden'); + confirmBtn.onclick = null; + cancelBtn.onclick = null; + inputEl.onkeydown = null; + }; + + const confirm = () => { + const val = inputEl.value.trim(); + closeModal(); + resolve(val); + }; + + const cancel = () => { + closeModal(); + resolve(null); + }; + + confirmBtn.onclick = confirm; + cancelBtn.onclick = cancel; + + inputEl.onkeydown = (e) => { + if (e.key === 'Enter') confirm(); + if (e.key === 'Escape') cancel(); + }; + + modal.classList.remove('hidden'); + inputEl.focus(); + }); + }; + + const renderLayers = () => { + if (!layersList) return; + + const layersArray = Array.from(layersMap.values()); + + if (layersArray.length === 0) { + layersList.innerHTML = ` +
+

This PDF has no layers (OCG).

+

Add a new layer to get started!

+
+ `; + return; + } + + // Sort layers by displayOrder + const sortedLayers = layersArray.sort((a, b) => a.displayOrder - b.displayOrder); + + layersList.innerHTML = sortedLayers.map((layer: LayerData) => ` +
+ +
+ ${!layer.locked ? `` : ''} + ${!layer.locked ? `` : ''} +
+
+ `).join(''); + + // Attach toggle handlers + layersList.querySelectorAll('input[type="checkbox"]').forEach((checkbox) => { + checkbox.addEventListener('change', (e) => { + const target = e.target as HTMLInputElement; + const xref = parseInt(target.dataset.xref || '0'); + const isOn = target.checked; + + try { + currentDoc.setLayerVisibility(xref, isOn); + const layer = Array.from(layersMap.values()).find(l => l.xref === xref); + if (layer) { + layer.on = isOn; + } + } catch (err) { + console.error('Failed to set layer visibility:', err); + target.checked = !isOn; + showAlert('Error', 'Failed to toggle layer visibility'); + } + }); + }); + + // Attach delete handlers + layersList.querySelectorAll('.layer-delete').forEach((btn) => { + btn.addEventListener('click', (e) => { + const target = e.target as HTMLButtonElement; + const xref = parseInt(target.dataset.xref || '0'); + const layer = Array.from(layersMap.values()).find(l => l.xref === xref); + + if (!layer) { + showAlert('Error', 'Layer not found'); + return; + } + + try { + currentDoc.deleteOCG(layer.number); + layersMap.delete(layer.number); + renderLayers(); + } catch (err) { + console.error('Failed to delete layer:', err); + showAlert('Error', 'Failed to delete layer'); + } + }); + }); + + layersList.querySelectorAll('.layer-add-child').forEach((btn) => { + btn.addEventListener('click', async (e) => { + const target = e.target as HTMLButtonElement; + const parentXref = parseInt(target.dataset.xref || '0'); + const parentLayer = Array.from(layersMap.values()).find(l => l.xref === parentXref); + + const childName = await promptForInput('Add Child Layer', `Enter name for child layer under "${parentLayer?.text || 'Layer'}":`); + + if (!childName || !childName.trim()) return; + + try { + const childXref = currentDoc.addOCGWithParent(childName.trim(), parentXref); + const parentDisplayOrder = parentLayer?.displayOrder || 0; + layersMap.forEach((l) => { + if (l.displayOrder > parentDisplayOrder) { + l.displayOrder += 1; + } + }); + + layersMap.set(childXref, { + number: childXref, + xref: childXref, + text: childName.trim(), + on: true, + locked: false, + depth: (parentLayer?.depth || 0) + 1, + parentXref: parentXref, + displayOrder: parentDisplayOrder + 1 + }); + + renderLayers(); + } catch (err) { + console.error('Failed to add child layer:', err); + showAlert('Error', 'Failed to add child layer'); + } + }); + }); + }; + + const loadLayers = async () => { + if (!currentFile) { + showAlert('No File', 'Please select a PDF file.'); + return; + } + + try { + showLoader('Loading engine...'); + await pymupdf.load(); + + showLoader(`Loading layers from ${currentFile.name}...`); + currentDoc = await pymupdf.open(currentFile); + + showLoader('Reading layer configuration...'); + const existingLayers = currentDoc.getLayerConfig(); + + // Reset and populate layers map + layersMap.clear(); + nextDisplayOrder = 0; + + existingLayers.forEach((layer: any) => { + layersMap.set(layer.number, { + number: layer.number, + xref: layer.xref ?? layer.number, + text: layer.text, + on: layer.on, + locked: layer.locked, + depth: layer.depth ?? 0, + parentXref: layer.parentXref ?? 0, + displayOrder: layer.displayOrder ?? nextDisplayOrder++ + }); + if ((layer.displayOrder ?? -1) >= nextDisplayOrder) { + nextDisplayOrder = layer.displayOrder + 1; + } + }); + + hideLoader(); + + // Hide upload zone, show layers container + if (dropZone) dropZone.style.display = 'none'; + if (processBtnContainer) processBtnContainer.classList.add('hidden'); + if (layersContainer) layersContainer.classList.remove('hidden'); + + renderLayers(); + setupLayerHandlers(); + + } catch (error: any) { + hideLoader(); + showAlert('Error', error.message || 'Failed to load PDF layers'); + console.error('Layers error:', error); + } + }; + + const setupLayerHandlers = () => { + const addLayerBtn = document.getElementById('add-layer-btn'); + const newLayerInput = document.getElementById('new-layer-name') as HTMLInputElement; + const saveLayersBtn = document.getElementById('save-layers-btn'); + + if (addLayerBtn && newLayerInput) { + addLayerBtn.onclick = () => { + const name = newLayerInput.value.trim(); + if (!name) { + showAlert('Invalid Name', 'Please enter a layer name'); + return; + } + + try { + const xref = currentDoc.addOCG(name); + newLayerInput.value = ''; + + const newDisplayOrder = nextDisplayOrder++; + layersMap.set(xref, { + number: xref, + xref: xref, + text: name, + on: true, + locked: false, + depth: 0, + parentXref: 0, + displayOrder: newDisplayOrder + }); + + renderLayers(); + } catch (err: any) { + showAlert('Error', 'Failed to add layer: ' + err.message); + } + }; + } + + if (saveLayersBtn) { + saveLayersBtn.onclick = () => { + try { + showLoader('Saving PDF with layer changes...'); + const pdfBytes = currentDoc.save(); + const blob = new Blob([new Uint8Array(pdfBytes)], { type: 'application/pdf' }); + const outName = currentFile!.name.replace(/\.pdf$/i, '') + '_layers.pdf'; + downloadFile(blob, outName); + hideLoader(); + resetState(); + showAlert('Success', 'PDF with layer changes saved!', 'success'); + } catch (err: any) { + hideLoader(); + showAlert('Error', 'Failed to save PDF: ' + err.message); + } + }; + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const file = files[0]; + if (file.type === 'application/pdf' || file.name.toLowerCase().endsWith('.pdf')) { + currentFile = file; + updateUI(); + } else { + showAlert('Invalid File', 'Please select a PDF file.'); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (processBtn) { + processBtn.addEventListener('click', loadLayers); + } +}); diff --git a/src/js/logic/pdf-to-csv-page.ts b/src/js/logic/pdf-to-csv-page.ts new file mode 100644 index 0000000..3415fe2 --- /dev/null +++ b/src/js/logic/pdf-to-csv-page.ts @@ -0,0 +1,172 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; +import { createIcons, icons } from 'lucide'; +import JSZip from 'jszip'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +const pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); +let file: File | null = null; + +const updateUI = () => { + const fileDisplayArea = document.getElementById('file-display-area'); + const optionsPanel = document.getElementById('options-panel'); + + if (!fileDisplayArea || !optionsPanel) return; + + fileDisplayArea.innerHTML = ''; + + if (file) { + optionsPanel.classList.remove('hidden'); + + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = resetState; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + + createIcons({ icons }); + } else { + optionsPanel.classList.add('hidden'); + } +}; + +const resetState = () => { + file = null; + const fileInput = document.getElementById('file-input') as HTMLInputElement; + if (fileInput) fileInput.value = ''; + updateUI(); +}; + +function tableToCsv(rows: (string | null)[][]): string { + return rows.map(row => + row.map(cell => { + const cellStr = cell ?? ''; + if (cellStr.includes(',') || cellStr.includes('"') || cellStr.includes('\n')) { + return `"${cellStr.replace(/"/g, '""')}"`; + } + return cellStr; + }).join(',') + ).join('\n'); +} + +async function convert() { + if (!file) { + showAlert('No File', 'Please upload a PDF file first.'); + return; + } + + showLoader('Loading Engine...'); + + try { + await pymupdf.load(); + showLoader('Extracting tables...'); + + const doc = await pymupdf.open(file); + const pageCount = doc.pageCount; + const baseName = file.name.replace(/\.[^/.]+$/, ''); + + const allRows: (string | null)[][] = []; + + for (let i = 0; i < pageCount; i++) { + showLoader(`Scanning page ${i + 1} of ${pageCount}...`); + const page = doc.getPage(i); + const tables = page.findTables(); + + tables.forEach((table) => { + allRows.push(...table.rows); + allRows.push([]); + }); + } + + if (allRows.length === 0) { + showAlert('No Tables Found', 'No tables were detected in this PDF.'); + return; + } + + const csvContent = tableToCsv(allRows.filter(row => row.length > 0)); + const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); + downloadFile(blob, `${baseName}.csv`); + showAlert('Success', 'PDF converted to CSV successfully!', 'success', resetState); + } catch (e) { + console.error(e); + const message = e instanceof Error ? e.message : 'Unknown error'; + showAlert('Error', `Failed to convert PDF to CSV. ${message}`); + } finally { + hideLoader(); + } +} + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const backBtn = document.getElementById('back-to-tools'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const handleFileSelect = (newFiles: FileList | null) => { + if (!newFiles || newFiles.length === 0) return; + const validFile = Array.from(newFiles).find(f => f.type === 'application/pdf'); + + if (!validFile) { + showAlert('Invalid File', 'Please upload a PDF file.'); + return; + } + + file = validFile; + updateUI(); + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (processBtn) { + processBtn.addEventListener('click', convert); + } +}); diff --git a/src/js/logic/pdf-to-docx-page.ts b/src/js/logic/pdf-to-docx-page.ts new file mode 100644 index 0000000..2d9e2b6 --- /dev/null +++ b/src/js/logic/pdf-to-docx-page.ts @@ -0,0 +1,203 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, readFileAsArrayBuffer, formatBytes, getPDFDocument } from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +const pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const fileDisplayArea = document.getElementById('file-display-area'); + const convertOptions = document.getElementById('convert-options'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!fileDisplayArea || !convertOptions || !processBtn || !fileControls) return; + + if (state.files.length > 0) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = `${formatBytes(file.size)} • Loading pages...`; + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_: File, i: number) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + + try { + const arrayBuffer = await readFileAsArrayBuffer(file); + const pdfDoc = await getPDFDocument({ data: arrayBuffer }).promise; + metaSpan.textContent = `${formatBytes(file.size)} • ${pdfDoc.numPages} pages`; + } catch (error) { + metaSpan.textContent = `${formatBytes(file.size)} • Could not load page count`; + } + } + + createIcons({ icons }); + fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + (processBtn as HTMLButtonElement).disabled = false; + } else { + fileDisplayArea.innerHTML = ''; + fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + (processBtn as HTMLButtonElement).disabled = true; + } + }; + + const resetState = () => { + state.files = []; + state.pdfDoc = null; + updateUI(); + }; + + const convert = async () => { + try { + if (state.files.length === 0) { + showAlert('No Files', 'Please select at least one PDF file.'); + return; + } + + showLoader('Loading PDF converter...'); + await pymupdf.load(); + + if (state.files.length === 1) { + const file = state.files[0]; + showLoader(`Converting ${file.name}...`); + + const docxBlob = await pymupdf.pdfToDocx(file); + const outName = file.name.replace(/\.pdf$/i, '') + '.docx'; + + downloadFile(docxBlob, outName); + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${file.name} to DOCX.`, + 'success', + () => resetState() + ); + } else { + showLoader('Converting multiple PDFs...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + + const docxBlob = await pymupdf.pdfToDocx(file); + const baseName = file.name.replace(/\.pdf$/i, ''); + const arrayBuffer = await docxBlob.arrayBuffer(); + zip.file(`${baseName}.docx`, arrayBuffer); + } + + showLoader('Creating ZIP archive...'); + const zipBlob = await zip.generateAsync({ type: 'blob' }); + + downloadFile(zipBlob, 'converted-documents.zip'); + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${state.files.length} PDF(s) to DOCX.`, + 'success', + () => resetState() + ); + } + } catch (e: any) { + hideLoader(); + showAlert('Error', `An error occurred during conversion. Error: ${e.message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const pdfFiles = Array.from(files).filter( + f => f.type === 'application/pdf' || f.name.toLowerCase().endsWith('.pdf') + ); + state.files = [...state.files, ...pdfFiles]; + updateUI(); + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const files = e.dataTransfer?.files; + if (files && files.length > 0) { + handleFileSelect(files); + } + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => { + fileInput.click(); + }); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', () => { + resetState(); + }); + } + + if (processBtn) { + processBtn.addEventListener('click', convert); + } +}); diff --git a/src/js/logic/pdf-to-excel-page.ts b/src/js/logic/pdf-to-excel-page.ts new file mode 100644 index 0000000..0d11648 --- /dev/null +++ b/src/js/logic/pdf-to-excel-page.ts @@ -0,0 +1,182 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; +import { createIcons, icons } from 'lucide'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; +import * as XLSX from 'xlsx'; + +const pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); +let file: File | null = null; + +const updateUI = () => { + const fileDisplayArea = document.getElementById('file-display-area'); + const optionsPanel = document.getElementById('options-panel'); + + if (!fileDisplayArea || !optionsPanel) return; + + fileDisplayArea.innerHTML = ''; + + if (file) { + optionsPanel.classList.remove('hidden'); + + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = resetState; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + + createIcons({ icons }); + } else { + optionsPanel.classList.add('hidden'); + } +}; + +const resetState = () => { + file = null; + const fileInput = document.getElementById('file-input') as HTMLInputElement; + if (fileInput) fileInput.value = ''; + updateUI(); +}; + +async function convert() { + if (!file) { + showAlert('No File', 'Please upload a PDF file first.'); + return; + } + + showLoader('Loading Engine...'); + + try { + await pymupdf.load(); + showLoader('Extracting tables...'); + + const doc = await pymupdf.open(file); + const pageCount = doc.pageCount; + const baseName = file.name.replace(/\.[^/.]+$/, ''); + + interface TableData { + page: number; + rows: (string | null)[][]; + } + + const allTables: TableData[] = []; + + for (let i = 0; i < pageCount; i++) { + showLoader(`Scanning page ${i + 1} of ${pageCount}...`); + const page = doc.getPage(i); + const tables = page.findTables(); + + tables.forEach((table) => { + allTables.push({ + page: i + 1, + rows: table.rows + }); + }); + } + + if (allTables.length === 0) { + showAlert('No Tables Found', 'No tables were detected in this PDF.'); + return; + } + + showLoader('Creating Excel file...'); + + const workbook = XLSX.utils.book_new(); + + if (allTables.length === 1) { + const worksheet = XLSX.utils.aoa_to_sheet(allTables[0].rows); + XLSX.utils.book_append_sheet(workbook, worksheet, 'Table'); + } else { + allTables.forEach((table, idx) => { + const sheetName = `Table ${idx + 1} (Page ${table.page})`.substring(0, 31); + const worksheet = XLSX.utils.aoa_to_sheet(table.rows); + XLSX.utils.book_append_sheet(workbook, worksheet, sheetName); + }); + } + + const xlsxData = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' }); + const blob = new Blob([xlsxData], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); + downloadFile(blob, `${baseName}.xlsx`); + showAlert('Success', `Extracted ${allTables.length} table(s) to Excel!`, 'success', resetState); + } catch (e) { + console.error(e); + const message = e instanceof Error ? e.message : 'Unknown error'; + showAlert('Error', `Failed to convert PDF to Excel. ${message}`); + } finally { + hideLoader(); + } +} + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const backBtn = document.getElementById('back-to-tools'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const handleFileSelect = (newFiles: FileList | null) => { + if (!newFiles || newFiles.length === 0) return; + const validFile = Array.from(newFiles).find(f => f.type === 'application/pdf'); + + if (!validFile) { + showAlert('Invalid File', 'Please upload a PDF file.'); + return; + } + + file = validFile; + updateUI(); + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (processBtn) { + processBtn.addEventListener('click', convert); + } +}); diff --git a/src/js/logic/pdf-to-markdown-page.ts b/src/js/logic/pdf-to-markdown-page.ts new file mode 100644 index 0000000..d35dc86 --- /dev/null +++ b/src/js/logic/pdf-to-markdown-page.ts @@ -0,0 +1,206 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, readFileAsArrayBuffer, formatBytes, getPDFDocument } from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +const pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const fileDisplayArea = document.getElementById('file-display-area'); + const convertOptions = document.getElementById('convert-options'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const includeImagesCheckbox = document.getElementById('include-images') as HTMLInputElement; + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!fileDisplayArea || !convertOptions || !processBtn || !fileControls) return; + + if (state.files.length > 0) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = `${formatBytes(file.size)} • Loading pages...`; + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_: File, i: number) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + + try { + const arrayBuffer = await readFileAsArrayBuffer(file); + const pdfDoc = await getPDFDocument({ data: arrayBuffer }).promise; + metaSpan.textContent = `${formatBytes(file.size)} • ${pdfDoc.numPages} pages`; + } catch (error) { + metaSpan.textContent = `${formatBytes(file.size)} • Could not load page count`; + } + } + + createIcons({ icons }); + fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + (processBtn as HTMLButtonElement).disabled = false; + } else { + fileDisplayArea.innerHTML = ''; + fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + (processBtn as HTMLButtonElement).disabled = true; + } + }; + + const resetState = () => { + state.files = []; + state.pdfDoc = null; + updateUI(); + }; + + const convert = async () => { + try { + if (state.files.length === 0) { + showAlert('No Files', 'Please select at least one PDF file.'); + return; + } + + showLoader('Loading PDF converter...'); + await pymupdf.load(); + + const includeImages = includeImagesCheckbox?.checked ?? false; + + if (state.files.length === 1) { + const file = state.files[0]; + showLoader(`Converting ${file.name}...`); + + const markdown = await pymupdf.pdfToMarkdown(file, { includeImages }); + const outName = file.name.replace(/\.pdf$/i, '') + '.md'; + const blob = new Blob([markdown], { type: 'text/markdown' }); + + downloadFile(blob, outName); + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${file.name} to Markdown.`, + 'success', + () => resetState() + ); + } else { + showLoader('Converting multiple PDFs...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + + const markdown = await pymupdf.pdfToMarkdown(file, { includeImages }); + const baseName = file.name.replace(/\.pdf$/i, ''); + zip.file(`${baseName}.md`, markdown); + } + + showLoader('Creating ZIP archive...'); + const zipBlob = await zip.generateAsync({ type: 'blob' }); + + downloadFile(zipBlob, 'markdown-files.zip'); + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${state.files.length} PDF(s) to Markdown.`, + 'success', + () => resetState() + ); + } + } catch (e: any) { + hideLoader(); + showAlert('Error', `An error occurred during conversion. Error: ${e.message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const pdfFiles = Array.from(files).filter( + f => f.type === 'application/pdf' || f.name.toLowerCase().endsWith('.pdf') + ); + state.files = [...state.files, ...pdfFiles]; + updateUI(); + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const files = e.dataTransfer?.files; + if (files && files.length > 0) { + handleFileSelect(files); + } + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => { + fileInput.click(); + }); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', () => { + resetState(); + }); + } + + if (processBtn) { + processBtn.addEventListener('click', convert); + } +}); diff --git a/src/js/logic/pdf-to-pdfa-page.ts b/src/js/logic/pdf-to-pdfa-page.ts new file mode 100644 index 0000000..5f392e4 --- /dev/null +++ b/src/js/logic/pdf-to-pdfa-page.ts @@ -0,0 +1,228 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { + downloadFile, + readFileAsArrayBuffer, + formatBytes, + getPDFDocument, +} from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { convertFileToPdfA, type PdfALevel } from '../utils/ghostscript-loader'; + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const fileDisplayArea = document.getElementById('file-display-area'); + const optionsContainer = document.getElementById('options-container'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const pdfaLevelSelect = document.getElementById('pdfa-level') as HTMLSelectElement; + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!fileDisplayArea || !optionsContainer || !processBtn || !fileControls) return; + + if (state.files.length > 0) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = `${formatBytes(file.size)} • Loading pages...`; + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + + try { + const arrayBuffer = await readFileAsArrayBuffer(file); + const pdfDoc = await getPDFDocument({ data: arrayBuffer }).promise; + metaSpan.textContent = `${formatBytes(file.size)} • ${pdfDoc.numPages} pages`; + } catch (error) { + console.error('Error loading PDF:', error); + metaSpan.textContent = `${formatBytes(file.size)} • Could not load page count`; + } + } + + createIcons({ icons }); + fileControls.classList.remove('hidden'); + optionsContainer.classList.remove('hidden'); + (processBtn as HTMLButtonElement).disabled = false; + } else { + fileDisplayArea.innerHTML = ''; + fileControls.classList.add('hidden'); + optionsContainer.classList.add('hidden'); + (processBtn as HTMLButtonElement).disabled = true; + } + }; + + const resetState = () => { + state.files = []; + state.pdfDoc = null; + + if (pdfaLevelSelect) pdfaLevelSelect.value = 'PDF/A-2b'; + + updateUI(); + }; + + const convertToPdfA = async () => { + const level = pdfaLevelSelect.value as PdfALevel; + + try { + if (state.files.length === 0) { + showAlert('No Files', 'Please select at least one PDF file.'); + hideLoader(); + return; + } + + if (state.files.length === 1) { + const originalFile = state.files[0]; + + showLoader('Initializing Ghostscript...'); + + const convertedBlob = await convertFileToPdfA( + originalFile, + level, + (msg) => showLoader(msg) + ); + + const fileName = originalFile.name.replace(/\.pdf$/i, '') + '_pdfa.pdf'; + + downloadFile(convertedBlob, fileName); + + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${originalFile.name} to ${level}.`, + 'success', + () => resetState() + ); + } else { + showLoader('Converting multiple PDFs to PDF/A...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + + const convertedBlob = await convertFileToPdfA( + file, + level, + (msg) => showLoader(msg) + ); + + const baseName = file.name.replace(/\.pdf$/i, ''); + const blobBuffer = await convertedBlob.arrayBuffer(); + zip.file(`${baseName}_pdfa.pdf`, blobBuffer); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + + downloadFile(zipBlob, 'pdfa-converted.zip'); + + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${state.files.length} PDF(s) to ${level}.`, + 'success', + () => resetState() + ); + } + } catch (e: any) { + hideLoader(); + showAlert( + 'Error', + `An error occurred during conversion. Error: ${e.message}` + ); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + state.files = [...state.files, ...Array.from(files)]; + updateUI(); + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const files = e.dataTransfer?.files; + if (files && files.length > 0) { + const pdfFiles = Array.from(files).filter(f => f.type === 'application/pdf' || f.name.toLowerCase().endsWith('.pdf')); + if (pdfFiles.length > 0) { + const dataTransfer = new DataTransfer(); + pdfFiles.forEach(f => dataTransfer.items.add(f)); + handleFileSelect(dataTransfer.files); + } + } + }); + + // Clear value on click to allow re-selecting the same file + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => { + fileInput.click(); + }); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', () => { + resetState(); + }); + } + + if (processBtn) { + processBtn.addEventListener('click', convertToPdfA); + } +}); diff --git a/src/js/logic/pdf-to-svg-page.ts b/src/js/logic/pdf-to-svg-page.ts new file mode 100644 index 0000000..6813e24 --- /dev/null +++ b/src/js/logic/pdf-to-svg-page.ts @@ -0,0 +1,202 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; +import { createIcons, icons } from 'lucide'; +import JSZip from 'jszip'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +const pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); +let files: File[] = []; + +const updateUI = () => { + const fileDisplayArea = document.getElementById('file-display-area'); + const optionsPanel = document.getElementById('options-panel'); + const fileControls = document.getElementById('file-controls'); + + if (!fileDisplayArea || !optionsPanel) return; + + fileDisplayArea.innerHTML = ''; + + if (files.length > 0) { + optionsPanel.classList.remove('hidden'); + if (fileControls) fileControls.classList.remove('hidden'); + + files.forEach((file, index) => { + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + files = files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + }); + + createIcons({ icons }); + } else { + optionsPanel.classList.add('hidden'); + if (fileControls) fileControls.classList.add('hidden'); + } +}; + +const resetState = () => { + files = []; + const fileInput = document.getElementById('file-input') as HTMLInputElement; + if (fileInput) fileInput.value = ''; + updateUI(); +}; + +async function convert() { + if (files.length === 0) { + showAlert('No Files', 'Please upload at least one PDF file.'); + return; + } + + showLoader('Loading Engine...'); + + try { + await pymupdf.load(); + + const isSingleFile = files.length === 1; + + if (isSingleFile) { + const doc = await pymupdf.open(files[0]); + const pageCount = doc.pageCount; + const baseName = files[0].name.replace(/\.[^/.]+$/, ''); + + if (pageCount === 1) { + showLoader('Converting to SVG...'); + const page = doc.getPage(0); + const svgContent = page.toSvg(); + const svgBlob = new Blob([svgContent], { type: 'image/svg+xml' }); + downloadFile(svgBlob, `${baseName}.svg`); + showAlert('Success', 'PDF converted to SVG successfully!', 'success', () => resetState()); + } else { + const zip = new JSZip(); + for (let i = 0; i < pageCount; i++) { + showLoader(`Converting page ${i + 1} of ${pageCount}...`); + const page = doc.getPage(i); + const svgContent = page.toSvg(); + zip.file(`page_${i + 1}.svg`, svgContent); + } + showLoader('Creating ZIP file...'); + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, `${baseName}_svg.zip`); + showAlert('Success', `Converted ${pageCount} pages to SVG!`, 'success', () => resetState()); + } + } else { + const zip = new JSZip(); + let totalPages = 0; + + for (let f = 0; f < files.length; f++) { + const file = files[f]; + showLoader(`Processing file ${f + 1} of ${files.length}...`); + const doc = await pymupdf.open(file); + const pageCount = doc.pageCount; + const baseName = file.name.replace(/\.[^/.]+$/, ''); + + for (let i = 0; i < pageCount; i++) { + showLoader(`File ${f + 1}/${files.length}: Page ${i + 1}/${pageCount}`); + const page = doc.getPage(i); + const svgContent = page.toSvg(); + const fileName = pageCount === 1 ? `${baseName}.svg` : `${baseName}_page_${i + 1}.svg`; + zip.file(fileName, svgContent); + totalPages++; + } + } + + showLoader('Creating ZIP file...'); + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, 'pdf_to_svg.zip'); + showAlert('Success', `Converted ${files.length} files (${totalPages} pages) to SVG!`, 'success', () => resetState()); + } + } catch (e) { + console.error(e); + const message = e instanceof Error ? e.message : 'Unknown error'; + showAlert('Error', `Failed to convert PDF to SVG. ${message}`); + } finally { + hideLoader(); + } +} + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const backBtn = document.getElementById('back-to-tools'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const handleFileSelect = (newFiles: FileList | null, replace = false) => { + if (!newFiles || newFiles.length === 0) return; + const validFiles = Array.from(newFiles).filter( + (file) => file.type === 'application/pdf' + ); + + if (validFiles.length === 0) { + showAlert('Invalid Files', 'Please upload PDF files.'); + return; + } + + if (replace) { + files = validFiles; + } else { + files = [...files, ...validFiles]; + } + updateUI(); + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files, files.length === 0); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null, files.length === 0); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) addMoreBtn.addEventListener('click', () => fileInput?.click()); + if (clearFilesBtn) clearFilesBtn.addEventListener('click', resetState); + if (processBtn) processBtn.addEventListener('click', convert); +}); diff --git a/src/js/logic/pdf-to-text-page.ts b/src/js/logic/pdf-to-text-page.ts new file mode 100644 index 0000000..1df7fba --- /dev/null +++ b/src/js/logic/pdf-to-text-page.ts @@ -0,0 +1,212 @@ +import { createIcons, icons } from 'lucide'; +import { showAlert, showLoader, hideLoader } from '../ui.js'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +let files: File[] = []; +let pymupdf: PyMuPDF | null = null; + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initializePage); +} else { + initializePage(); +} + +function initializePage() { + createIcons({ icons }); + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const processBtn = document.getElementById('process-btn') as HTMLButtonElement; + + if (fileInput) { + fileInput.addEventListener('change', handleFileUpload); + } + + if (dropZone) { + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-600'); + }); + + dropZone.addEventListener('dragleave', () => { + dropZone.classList.remove('bg-gray-600'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-600'); + const droppedFiles = e.dataTransfer?.files; + if (droppedFiles && droppedFiles.length > 0) { + handleFiles(droppedFiles); + } + }); + + fileInput?.addEventListener('click', () => { + if (fileInput) fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => { + fileInput?.click(); + }); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', () => { + files = []; + updateUI(); + }); + } + + if (processBtn) { + processBtn.addEventListener('click', extractText); + } + + document.getElementById('back-to-tools')?.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); +} + +function handleFileUpload(e: Event) { + const input = e.target as HTMLInputElement; + if (input.files && input.files.length > 0) { + handleFiles(input.files); + } +} + +function handleFiles(newFiles: FileList) { + const validFiles = Array.from(newFiles).filter(file => + file.type === 'application/pdf' || file.name.toLowerCase().endsWith('.pdf') + ); + + if (validFiles.length < newFiles.length) { + showAlert('Invalid Files', 'Some files were skipped. Only PDF files are allowed.'); + } + + if (validFiles.length > 0) { + files = [...files, ...validFiles]; + updateUI(); + } +} + +const resetState = () => { + files = []; + updateUI(); +}; + +function updateUI() { + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const extractOptions = document.getElementById('extract-options'); + + if (!fileDisplayArea || !fileControls || !extractOptions) return; + + fileDisplayArea.innerHTML = ''; + + if (files.length > 0) { + fileControls.classList.remove('hidden'); + extractOptions.classList.remove('hidden'); + + files.forEach((file, index) => { + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex items-center gap-2 overflow-hidden'; + + const nameSpan = document.createElement('span'); + nameSpan.className = 'truncate font-medium text-gray-200'; + nameSpan.textContent = file.name; + + const sizeSpan = document.createElement('span'); + sizeSpan.className = 'flex-shrink-0 text-gray-400 text-xs'; + sizeSpan.textContent = `(${formatBytes(file.size)})`; + + infoContainer.append(nameSpan, sizeSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + files = files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + }); + createIcons({ icons }); + } else { + fileControls.classList.add('hidden'); + extractOptions.classList.add('hidden'); + } +} + +async function ensurePyMuPDF(): Promise { + if (!pymupdf) { + pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); + await pymupdf.load(); + } + return pymupdf; +} + +async function extractText() { + if (files.length === 0) { + showAlert('No Files', 'Please select at least one PDF file.'); + return; + } + + showLoader('Loading engine...'); + + try { + const mupdf = await ensurePyMuPDF(); + + if (files.length === 1) { + const file = files[0]; + showLoader(`Extracting text from ${file.name}...`); + + const fullText = await mupdf.pdfToText(file); + + const baseName = file.name.replace(/\.pdf$/i, ''); + const textBlob = new Blob([fullText], { type: 'text/plain;charset=utf-8' }); + downloadFile(textBlob, `${baseName}.txt`); + + hideLoader(); + showAlert('Success', 'Text extracted successfully!', 'success', () => { + resetState(); + }); + } else { + showLoader('Extracting text from multiple files...'); + + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < files.length; i++) { + const file = files[i]; + showLoader(`Extracting text from file ${i + 1}/${files.length}: ${file.name}...`); + + const fullText = await mupdf.pdfToText(file); + + const baseName = file.name.replace(/\.pdf$/i, ''); + zip.file(`${baseName}.txt`, fullText); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, 'pdf-to-text.zip'); + + hideLoader(); + showAlert('Success', `Extracted text from ${files.length} PDF files!`, 'success', () => { + resetState(); + }); + } + } catch (e: any) { + console.error('[PDFToText]', e); + hideLoader(); + showAlert('Extraction Error', e.message || 'Failed to extract text from PDF.'); + } +} diff --git a/src/js/logic/posterize-page.ts b/src/js/logic/posterize-page.ts index 52b687f..ffc12d9 100644 --- a/src/js/logic/posterize-page.ts +++ b/src/js/logic/posterize-page.ts @@ -3,17 +3,10 @@ import { downloadFile, parsePageRanges, getPDFDocument, formatBytes } from '../u import { PDFDocument, PageSizes } from 'pdf-lib'; import * as pdfjsLib from 'pdfjs-dist'; import { createIcons, icons } from 'lucide'; +import { PosterizeState } from '@/types'; pdfjsLib.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString(); -interface PosterizeState { - file: File | null; - pdfJsDoc: pdfjsLib.PDFDocumentProxy | null; - pdfBytes: Uint8Array | null; - pageSnapshots: Record; - currentPage: number; -} - const pageState: PosterizeState = { file: null, pdfJsDoc: null, @@ -143,7 +136,7 @@ async function posterize() { const rows = parseInt((document.getElementById('posterize-rows') as HTMLInputElement).value) || 1; const cols = parseInt((document.getElementById('posterize-cols') as HTMLInputElement).value) || 1; const pageSizeKey = (document.getElementById('output-page-size') as HTMLSelectElement).value as keyof typeof PageSizes; - let orientation = (document.getElementById('output-orientation') as HTMLSelectElement).value; + const orientation = (document.getElementById('output-orientation') as HTMLSelectElement).value; const scalingMode = (document.querySelector('input[name="scaling-mode"]:checked') as HTMLInputElement).value; const overlap = parseFloat((document.getElementById('overlap') as HTMLInputElement).value) || 0; const overlapUnits = (document.getElementById('overlap-units') as HTMLSelectElement).value; diff --git a/src/js/logic/powerpoint-to-pdf-page.ts b/src/js/logic/powerpoint-to-pdf-page.ts new file mode 100644 index 0000000..130fac5 --- /dev/null +++ b/src/js/logic/powerpoint-to-pdf-page.ts @@ -0,0 +1,218 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { + downloadFile, + readFileAsArrayBuffer, + formatBytes, +} from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { getLibreOfficeConverter, type LoadProgress } from '../utils/libreoffice-loader.js'; + +document.addEventListener('DOMContentLoaded', () => { + state.files = []; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const convertOptions = document.getElementById('convert-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const processBtn = document.getElementById('process-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!convertOptions) return; + + if (state.files.length > 0) { + if (fileDisplayArea) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + } + if (fileControls) fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + } else { + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + if (fileControls) fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + state.pdfDoc = null; + updateUI(); + }; + + const convertToPdf = async () => { + try { + if (state.files.length === 0) { + showAlert('No Files', 'Please select at least one PowerPoint file.'); + hideLoader(); + return; + } + + const converter = getLibreOfficeConverter(); + + // Initialize LibreOffice if not already done + await converter.initialize((progress: LoadProgress) => { + showLoader(progress.message, progress.percent); + }); + + if (state.files.length === 1) { + const originalFile = state.files[0]; + + showLoader('Processing...'); + + const pdfBlob = await converter.convertToPdf(originalFile); + + const fileName = originalFile.name.replace(/\.(ppt|pptx|odp)$/i, '') + '.pdf'; + + downloadFile(pdfBlob, fileName); + + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${originalFile.name} to PDF.`, + 'success', + () => resetState() + ); + } else { + showLoader('Processing...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.(ppt|pptx|odp)$/i, ''); + const pdfBuffer = await pdfBlob.arrayBuffer(); + zip.file(`${baseName}.pdf`, pdfBuffer); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + + downloadFile(zipBlob, 'powerpoint-converted.zip'); + + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${state.files.length} PowerPoint file(s) to PDF.`, + 'success', + () => resetState() + ); + } + } catch (e: any) { + hideLoader(); + showAlert( + 'Error', + `An error occurred during conversion. Error: ${e.message}` + ); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + state.files = [...state.files, ...Array.from(files)]; + updateUI(); + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const files = e.dataTransfer?.files; + if (files && files.length > 0) { + const pptFiles = Array.from(files).filter(f => { + const name = f.name.toLowerCase(); + return name.endsWith('.ppt') || name.endsWith('.pptx') || name.endsWith('.odp'); + }); + if (pptFiles.length > 0) { + const dataTransfer = new DataTransfer(); + pptFiles.forEach(f => dataTransfer.items.add(f)); + handleFileSelect(dataTransfer.files); + } + } + }); + + // Clear value on click to allow re-selecting the same file + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => { + fileInput.click(); + }); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', () => { + resetState(); + }); + } + + if (processBtn) { + processBtn.addEventListener('click', convertToPdf); + } + + updateUI(); +}); diff --git a/src/js/logic/prepare-pdf-for-ai-page.ts b/src/js/logic/prepare-pdf-for-ai-page.ts new file mode 100644 index 0000000..a1981e4 --- /dev/null +++ b/src/js/logic/prepare-pdf-for-ai-page.ts @@ -0,0 +1,204 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, readFileAsArrayBuffer, formatBytes, getPDFDocument } from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +const pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const fileDisplayArea = document.getElementById('file-display-area'); + const extractOptions = document.getElementById('extract-options'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!fileDisplayArea || !extractOptions || !processBtn || !fileControls) return; + + if (state.files.length > 0) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = `${formatBytes(file.size)} • Loading pages...`; + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + + try { + const arrayBuffer = await readFileAsArrayBuffer(file); + const pdfDoc = await getPDFDocument({ data: arrayBuffer }).promise; + metaSpan.textContent = `${formatBytes(file.size)} • ${pdfDoc.numPages} pages`; + } catch (error) { + console.error('Error loading PDF:', error); + metaSpan.textContent = `${formatBytes(file.size)} • Could not load page count`; + } + } + + createIcons({ icons }); + fileControls.classList.remove('hidden'); + extractOptions.classList.remove('hidden'); + (processBtn as HTMLButtonElement).disabled = false; + } else { + fileDisplayArea.innerHTML = ''; + fileControls.classList.add('hidden'); + extractOptions.classList.add('hidden'); + (processBtn as HTMLButtonElement).disabled = true; + } + }; + + const resetState = () => { + state.files = []; + state.pdfDoc = null; + updateUI(); + }; + + const extractForAI = async () => { + try { + if (state.files.length === 0) { + showAlert('No Files', 'Please select at least one PDF file.'); + return; + } + + showLoader('Loading engine...'); + await pymupdf.load(); + + const total = state.files.length; + let completed = 0; + let failed = 0; + + if (total === 1) { + const file = state.files[0]; + showLoader(`Extracting ${file.name} for AI...`); + + const llamaDocs = await (pymupdf as any).pdfToLlamaIndex(file); + const outName = file.name.replace(/\.pdf$/i, '') + '_llm.json'; + const jsonContent = JSON.stringify(llamaDocs, null, 2); + downloadFile(new Blob([jsonContent], { type: 'application/json' }), outName); + + hideLoader(); + showAlert('Extraction Complete', `Successfully extracted PDF for AI/LLM use.`, 'success', () => resetState()); + } else { + // Multiple files - create ZIP + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (const file of state.files) { + try { + showLoader(`Extracting ${file.name} for AI (${completed + 1}/${total})...`); + + const llamaDocs = await (pymupdf as any).pdfToLlamaIndex(file); + const outName = file.name.replace(/\.pdf$/i, '') + '_llm.json'; + const jsonContent = JSON.stringify(llamaDocs, null, 2); + zip.file(outName, jsonContent); + + completed++; + } catch (error) { + console.error(`Failed to extract ${file.name}:`, error); + failed++; + } + } + + showLoader('Creating ZIP archive...'); + const zipBlob = await zip.generateAsync({ type: 'blob' }); + + downloadFile(zipBlob, 'pdf-for-ai.zip'); + + hideLoader(); + + if (failed === 0) { + showAlert('Extraction Complete', `Successfully extracted ${completed} PDF(s) for AI/LLM use.`, 'success', () => resetState()); + } else { + showAlert('Extraction Partial', `Extracted ${completed} PDF(s), failed ${failed}.`, 'warning', () => resetState()); + } + } + } catch (e: any) { + hideLoader(); + showAlert('Error', `An error occurred during extraction. Error: ${e.message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const pdfFiles = Array.from(files).filter(f => f.type === 'application/pdf' || f.name.toLowerCase().endsWith('.pdf')); + if (pdfFiles.length > 0) { + state.files = [...state.files, ...pdfFiles]; + updateUI(); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => { + fileInput.click(); + }); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', resetState); + } + + if (processBtn) { + processBtn.addEventListener('click', extractForAI); + } +}); diff --git a/src/js/logic/psd-to-pdf-page.ts b/src/js/logic/psd-to-pdf-page.ts new file mode 100644 index 0000000..5f25ff8 --- /dev/null +++ b/src/js/logic/psd-to-pdf-page.ts @@ -0,0 +1,134 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +const ACCEPTED_EXTENSIONS = ['.psd']; +const FILETYPE_NAME = 'PSD'; + +let pymupdf: PyMuPDF | null = null; + +async function ensurePyMuPDF(): Promise { + if (!pymupdf) { + pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); + await pymupdf.load(); + } + return pymupdf; +} + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!fileDisplayArea || !processBtn || !fileControls) return; + if (state.files.length > 0) { + fileDisplayArea.innerHTML = ''; + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + infoContainer.append(nameSpan, metaSpan); + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + createIcons({ icons }); + fileControls.classList.remove('hidden'); + processBtn.classList.remove('hidden'); + } else { + fileDisplayArea.innerHTML = ''; + fileControls.classList.add('hidden'); + processBtn.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + updateUI(); + }; + + const convert = async () => { + if (state.files.length === 0) { + showAlert('No Files', `Please select at least one ${FILETYPE_NAME} file.`); + return; + } + try { + showLoader('Loading engine...'); + const mupdf = await ensurePyMuPDF(); + + if (state.files.length === 1) { + const file = state.files[0]; + showLoader(`Converting ${file.name}...`); + const pdfBlob = await mupdf.imageToPdf(file, { imageType: 'psd' }); + const baseName = file.name.replace(/\.[^/.]+$/, ''); + downloadFile(pdfBlob, `${baseName}.pdf`); + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${file.name} to PDF.`, 'success', () => resetState()); + } else { + showLoader('Converting multiple files...'); + const pdfBlob = await mupdf.imagesToPdf(state.files); + downloadFile(pdfBlob, 'psd_to_pdf.pdf'); + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${state.files.length} PSD files to a single PDF.`, 'success', () => resetState()); + } + } catch (err) { + hideLoader(); + const message = err instanceof Error ? err.message : 'Unknown error'; + console.error(`[${FILETYPE_NAME}ToPDF] Error:`, err); + showAlert('Error', `An error occurred during conversion. Error: ${message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(file => { + const ext = '.' + file.name.split('.').pop()?.toLowerCase(); + return ACCEPTED_EXTENSIONS.includes(ext); + }); + if (validFiles.length > 0) { + state.files = [...state.files, ...validFiles]; + updateUI(); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => handleFileSelect((e.target as HTMLInputElement).files)); + dropZone.addEventListener('dragover', (e) => { e.preventDefault(); dropZone.classList.add('bg-gray-700'); }); + dropZone.addEventListener('dragleave', (e) => { e.preventDefault(); dropZone.classList.remove('bg-gray-700'); }); + dropZone.addEventListener('drop', (e) => { e.preventDefault(); dropZone.classList.remove('bg-gray-700'); handleFileSelect(e.dataTransfer?.files ?? null); }); + fileInput.addEventListener('click', () => { fileInput.value = ''; }); + } + if (addMoreBtn) addMoreBtn.addEventListener('click', () => fileInput.click()); + if (clearFilesBtn) clearFilesBtn.addEventListener('click', resetState); + if (processBtn) processBtn.addEventListener('click', convert); +}); diff --git a/src/js/logic/pub-to-pdf-page.ts b/src/js/logic/pub-to-pdf-page.ts new file mode 100644 index 0000000..1c2e682 --- /dev/null +++ b/src/js/logic/pub-to-pdf-page.ts @@ -0,0 +1,142 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { getLibreOfficeConverter, type LoadProgress } from '../utils/libreoffice-loader.js'; + +const ACCEPTED_EXTENSIONS = ['.pub']; +const FILETYPE_NAME = 'PUB'; + +document.addEventListener('DOMContentLoaded', () => { + state.files = []; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const convertOptions = document.getElementById('convert-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const processBtn = document.getElementById('process-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!convertOptions) return; + + if (state.files.length > 0) { + if (fileDisplayArea) { + fileDisplayArea.innerHTML = ''; + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + infoContainer.append(nameSpan, metaSpan); + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + createIcons({ icons }); + } + if (fileControls) fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + } else { + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + if (fileControls) fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + updateUI(); + }; + + const convert = async () => { + if (state.files.length === 0) { + showAlert('No Files', `Please select at least one ${FILETYPE_NAME} file.`); + return; + } + try { + const converter = getLibreOfficeConverter(); + showLoader('Loading engine...'); + await converter.initialize((progress: LoadProgress) => { + showLoader(progress.message, progress.percent); + }); + if (state.files.length === 1) { + const file = state.files[0]; + showLoader(`Converting ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + const baseName = file.name.replace(/\.[^/.]+$/, ''); + downloadFile(pdfBlob, `${baseName}.pdf`); + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${file.name} to PDF.`, 'success', () => resetState()); + } else { + showLoader('Converting multiple files...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + const baseName = file.name.replace(/\.[^/.]+$/, ''); + zip.file(`${baseName}.pdf`, pdfBlob); + } + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, `${FILETYPE_NAME.toLowerCase()}-to-pdf.zip`); + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${state.files.length} files to PDF.`, 'success', () => resetState()); + } + } catch (err) { + hideLoader(); + const message = err instanceof Error ? err.message : 'Unknown error'; + console.error(`[${FILETYPE_NAME}ToPDF] Error:`, err); + showAlert('Error', `An error occurred during conversion. Error: ${message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(file => { + const ext = '.' + file.name.split('.').pop()?.toLowerCase(); + return ACCEPTED_EXTENSIONS.includes(ext); + }); + if (validFiles.length > 0) { + state.files = [...state.files, ...validFiles]; + updateUI(); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => handleFileSelect((e.target as HTMLInputElement).files)); + dropZone.addEventListener('dragover', (e) => { e.preventDefault(); dropZone.classList.add('bg-gray-700'); }); + dropZone.addEventListener('dragleave', (e) => { e.preventDefault(); dropZone.classList.remove('bg-gray-700'); }); + dropZone.addEventListener('drop', (e) => { e.preventDefault(); dropZone.classList.remove('bg-gray-700'); handleFileSelect(e.dataTransfer?.files ?? null); }); + fileInput.addEventListener('click', () => { fileInput.value = ''; }); + } + if (addMoreBtn) addMoreBtn.addEventListener('click', () => fileInput.click()); + if (clearFilesBtn) clearFilesBtn.addEventListener('click', resetState); + if (processBtn) processBtn.addEventListener('click', convert); + + updateUI(); +}); diff --git a/src/js/logic/rasterize-pdf-page.ts b/src/js/logic/rasterize-pdf-page.ts new file mode 100644 index 0000000..83f081b --- /dev/null +++ b/src/js/logic/rasterize-pdf-page.ts @@ -0,0 +1,219 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, readFileAsArrayBuffer, formatBytes, getPDFDocument } from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +const pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const fileDisplayArea = document.getElementById('file-display-area'); + const rasterizeOptions = document.getElementById('rasterize-options'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!fileDisplayArea || !rasterizeOptions || !processBtn || !fileControls) return; + + if (state.files.length > 0) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = `${formatBytes(file.size)} • Loading pages...`; + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + + try { + const arrayBuffer = await readFileAsArrayBuffer(file); + const pdfDoc = await getPDFDocument({ data: arrayBuffer }).promise; + metaSpan.textContent = `${formatBytes(file.size)} • ${pdfDoc.numPages} pages`; + } catch (error) { + console.error('Error loading PDF:', error); + metaSpan.textContent = `${formatBytes(file.size)} • Could not load page count`; + } + } + + createIcons({ icons }); + fileControls.classList.remove('hidden'); + rasterizeOptions.classList.remove('hidden'); + (processBtn as HTMLButtonElement).disabled = false; + } else { + fileDisplayArea.innerHTML = ''; + fileControls.classList.add('hidden'); + rasterizeOptions.classList.add('hidden'); + (processBtn as HTMLButtonElement).disabled = true; + } + }; + + const resetState = () => { + state.files = []; + state.pdfDoc = null; + updateUI(); + }; + + const rasterize = async () => { + try { + if (state.files.length === 0) { + showAlert('No Files', 'Please select at least one PDF file.'); + return; + } + + showLoader('Loading engine...'); + await pymupdf.load(); + + // Get options from UI + const dpi = parseInt((document.getElementById('rasterize-dpi') as HTMLSelectElement).value) || 150; + const format = (document.getElementById('rasterize-format') as HTMLSelectElement).value as 'png' | 'jpeg'; + const grayscale = (document.getElementById('rasterize-grayscale') as HTMLInputElement).checked; + + const total = state.files.length; + let completed = 0; + let failed = 0; + + if (total === 1) { + const file = state.files[0]; + showLoader(`Rasterizing ${file.name}...`); + + const rasterizedBlob = await (pymupdf as any).rasterizePdf(file, { + dpi, + format, + grayscale, + quality: 95 + }); + + const outName = file.name.replace(/\.pdf$/i, '') + '_rasterized.pdf'; + downloadFile(rasterizedBlob, outName); + + hideLoader(); + showAlert('Rasterization Complete', `Successfully rasterized PDF at ${dpi} DPI.`, 'success', () => resetState()); + } else { + // Multiple files - create ZIP + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (const file of state.files) { + try { + showLoader(`Rasterizing ${file.name} (${completed + 1}/${total})...`); + + const rasterizedBlob = await (pymupdf as any).rasterizePdf(file, { + dpi, + format, + grayscale, + quality: 95 + }); + + const outName = file.name.replace(/\.pdf$/i, '') + '_rasterized.pdf'; + zip.file(outName, rasterizedBlob); + + completed++; + } catch (error) { + console.error(`Failed to rasterize ${file.name}:`, error); + failed++; + } + } + + showLoader('Creating ZIP archive...'); + const zipBlob = await zip.generateAsync({ type: 'blob' }); + + downloadFile(zipBlob, 'rasterized-pdfs.zip'); + + hideLoader(); + + if (failed === 0) { + showAlert('Rasterization Complete', `Successfully rasterized ${completed} PDF(s) at ${dpi} DPI.`, 'success', () => resetState()); + } else { + showAlert('Rasterization Partial', `Rasterized ${completed} PDF(s), failed ${failed}.`, 'warning', () => resetState()); + } + } + } catch (e: any) { + hideLoader(); + showAlert('Error', `An error occurred during rasterization. Error: ${e.message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const pdfFiles = Array.from(files).filter(f => f.type === 'application/pdf' || f.name.toLowerCase().endsWith('.pdf')); + if (pdfFiles.length > 0) { + state.files = [...state.files, ...pdfFiles]; + updateUI(); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => { + fileInput.click(); + }); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', resetState); + } + + if (processBtn) { + processBtn.addEventListener('click', rasterize); + } +}); diff --git a/src/js/logic/remove-restrictions-page.ts b/src/js/logic/remove-restrictions-page.ts index 3cb9176..98404e2 100644 --- a/src/js/logic/remove-restrictions-page.ts +++ b/src/js/logic/remove-restrictions-page.ts @@ -1,12 +1,9 @@ import { showAlert } from '../ui.js'; import { downloadFile, formatBytes, initializeQpdf, readFileAsArrayBuffer } from '../utils/helpers.js'; import { icons, createIcons } from 'lucide'; +import { RemoveRestrictionsState } from '@/types'; -interface PageState { - file: File | null; -} - -const pageState: PageState = { +const pageState: RemoveRestrictionsState = { file: null, }; diff --git a/src/js/logic/rotate-custom-page.ts b/src/js/logic/rotate-custom-page.ts new file mode 100644 index 0000000..2d5ebec --- /dev/null +++ b/src/js/logic/rotate-custom-page.ts @@ -0,0 +1,386 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, formatBytes, getPDFDocument } from '../utils/helpers.js'; +import { createIcons, icons } from 'lucide'; +import { PDFDocument as PDFLibDocument, degrees } from 'pdf-lib'; +import { renderPagesProgressively, cleanupLazyRendering } from '../utils/render-utils.js'; +import * as pdfjsLib from 'pdfjs-dist'; + +pdfjsLib.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString(); + +interface RotateState { + file: File | null; + pdfDoc: PDFLibDocument | null; + pdfJsDoc: pdfjsLib.PDFDocumentProxy | null; + rotations: number[]; +} + +const pageState: RotateState = { + file: null, + pdfDoc: null, + pdfJsDoc: null, + rotations: [], +}; + +function resetState() { + cleanupLazyRendering(); + pageState.file = null; + pageState.pdfDoc = null; + pageState.pdfJsDoc = null; + pageState.rotations = []; + + const fileDisplayArea = document.getElementById('file-display-area'); + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + + const toolOptions = document.getElementById('tool-options'); + if (toolOptions) toolOptions.classList.add('hidden'); + + const pageThumbnails = document.getElementById('page-thumbnails'); + if (pageThumbnails) pageThumbnails.innerHTML = ''; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + if (fileInput) fileInput.value = ''; + + const batchAngle = document.getElementById('batch-custom-angle') as HTMLInputElement; + if (batchAngle) batchAngle.value = '0'; +} + +function updateAllRotationDisplays() { + for (let i = 0; i < pageState.rotations.length; i++) { + const input = document.getElementById(`page-angle-${i}`) as HTMLInputElement; + if (input) input.value = pageState.rotations[i].toString(); + const container = document.querySelector(`[data-page-index="${i}"]`); + if (container) { + const wrapper = container.querySelector('.thumbnail-wrapper') as HTMLElement; + if (wrapper) wrapper.style.transform = `rotate(${-pageState.rotations[i]}deg)`; + } + } +} + +function createPageWrapper(canvas: HTMLCanvasElement, pageNumber: number): HTMLElement { + const pageIndex = pageNumber - 1; + + const container = document.createElement('div'); + container.className = 'page-thumbnail relative bg-gray-700 rounded-lg overflow-hidden'; + container.dataset.pageIndex = pageIndex.toString(); + container.dataset.pageNumber = pageNumber.toString(); + + const canvasWrapper = document.createElement('div'); + canvasWrapper.className = 'thumbnail-wrapper flex items-center justify-center p-2 h-36'; + canvasWrapper.style.transition = 'transform 0.3s ease'; + // Apply initial rotation if it exists (negated for canvas display) + const initialRotation = pageState.rotations[pageIndex] || 0; + canvasWrapper.style.transform = `rotate(${-initialRotation}deg)`; + + canvas.className = 'max-w-full max-h-full object-contain'; + canvasWrapper.appendChild(canvas); + + const pageLabel = document.createElement('div'); + pageLabel.className = 'absolute top-1 left-1 bg-black bg-opacity-60 text-white text-xs px-2 py-1 rounded'; + pageLabel.textContent = `${pageNumber}`; + + container.appendChild(canvasWrapper); + container.appendChild(pageLabel); + + // Per-page rotation controls - Custom angle input + const controls = document.createElement('div'); + controls.className = 'flex items-center justify-center gap-1 p-2 bg-gray-800'; + + const decrementBtn = document.createElement('button'); + decrementBtn.className = 'w-8 h-8 flex items-center justify-center bg-gray-700 hover:bg-gray-600 text-white rounded border border-gray-600 text-sm'; + decrementBtn.textContent = '-'; + decrementBtn.onclick = function (e) { + e.stopPropagation(); + const input = document.getElementById(`page-angle-${pageIndex}`) as HTMLInputElement; + const current = parseInt(input.value) || 0; + input.value = (current - 1).toString(); + }; + + const angleInput = document.createElement('input'); + angleInput.type = 'number'; + angleInput.id = `page-angle-${pageIndex}`; + angleInput.value = pageState.rotations[pageIndex]?.toString() || '0'; + angleInput.className = 'w-12 h-8 text-center bg-gray-700 border border-gray-600 text-white rounded text-xs'; + + const incrementBtn = document.createElement('button'); + incrementBtn.className = 'w-8 h-8 flex items-center justify-center bg-gray-700 hover:bg-gray-600 text-white rounded border border-gray-600 text-sm'; + incrementBtn.textContent = '+'; + incrementBtn.onclick = function (e) { + e.stopPropagation(); + const input = document.getElementById(`page-angle-${pageIndex}`) as HTMLInputElement; + const current = parseInt(input.value) || 0; + input.value = (current + 1).toString(); + }; + + const applyBtn = document.createElement('button'); + applyBtn.className = 'w-8 h-8 flex items-center justify-center bg-gray-700 hover:bg-gray-600 text-white rounded border border-gray-600'; + applyBtn.innerHTML = ''; + applyBtn.onclick = function (e) { + e.stopPropagation(); + const input = document.getElementById(`page-angle-${pageIndex}`) as HTMLInputElement; + const angle = parseInt(input.value) || 0; + pageState.rotations[pageIndex] = angle; + const wrapper = container.querySelector('.thumbnail-wrapper') as HTMLElement; + if (wrapper) wrapper.style.transform = `rotate(${-angle}deg)`; + }; + + controls.append(decrementBtn, angleInput, incrementBtn, applyBtn); + container.appendChild(controls); + + // Re-create icons for the new element + setTimeout(function () { + createIcons({ icons }); + }, 0); + + return container; +} + +async function renderThumbnails() { + const pageThumbnails = document.getElementById('page-thumbnails'); + if (!pageThumbnails || !pageState.pdfJsDoc) return; + + pageThumbnails.innerHTML = ''; + + await renderPagesProgressively( + pageState.pdfJsDoc, + pageThumbnails, + createPageWrapper, + { + batchSize: 8, + useLazyLoading: true, + lazyLoadMargin: '200px', + eagerLoadBatches: 2, + onBatchComplete: function () { + createIcons({ icons }); + } + } + ); + + createIcons({ icons }); +} + +async function updateUI() { + const fileDisplayArea = document.getElementById('file-display-area'); + const toolOptions = document.getElementById('tool-options'); + + if (!fileDisplayArea) return; + + fileDisplayArea.innerHTML = ''; + + if (pageState.file) { + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = pageState.file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = `${formatBytes(pageState.file.size)} • Loading...`; + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = function () { + resetState(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + createIcons({ icons }); + + try { + showLoader('Loading PDF...'); + const arrayBuffer = await pageState.file.arrayBuffer(); + + pageState.pdfDoc = await PDFLibDocument.load(arrayBuffer.slice(0), { + ignoreEncryption: true, + throwOnInvalidObject: false + }); + + pageState.pdfJsDoc = await getPDFDocument({ data: arrayBuffer.slice(0) }).promise; + + const pageCount = pageState.pdfDoc.getPageCount(); + pageState.rotations = new Array(pageCount).fill(0); + + metaSpan.textContent = `${formatBytes(pageState.file.size)} • ${pageCount} pages`; + + await renderThumbnails(); + hideLoader(); + + if (toolOptions) toolOptions.classList.remove('hidden'); + } catch (error) { + console.error('Error loading PDF:', error); + hideLoader(); + showAlert('Error', 'Failed to load PDF file.'); + resetState(); + } + } else { + if (toolOptions) toolOptions.classList.add('hidden'); + } +} + +async function applyRotations() { + if (!pageState.pdfDoc || !pageState.file) { + showAlert('Error', 'Please upload a PDF first.'); + return; + } + + showLoader('Applying rotations...'); + + try { + const pageCount = pageState.pdfDoc.getPageCount(); + const newPdfDoc = await PDFLibDocument.create(); + + for (let i = 0; i < pageCount; i++) { + const rotation = pageState.rotations[i] || 0; + const originalPage = pageState.pdfDoc.getPage(i); + const currentRotation = originalPage.getRotation().angle; + const totalRotation = currentRotation + rotation; + + console.log(`Page ${i}: rotation=${rotation}, currentRotation=${currentRotation}, totalRotation=${totalRotation}, applying=${-totalRotation}`); + + if (totalRotation % 90 === 0) { + const [copiedPage] = await newPdfDoc.copyPages(pageState.pdfDoc, [i]); + copiedPage.setRotation(degrees(totalRotation)); + newPdfDoc.addPage(copiedPage); + } else { + const embeddedPage = await newPdfDoc.embedPage(originalPage); + const { width, height } = embeddedPage.scale(1); + + const angleRad = (totalRotation * Math.PI) / 180; + const absCos = Math.abs(Math.cos(angleRad)); + const absSin = Math.abs(Math.sin(angleRad)); + + const newWidth = width * absCos + height * absSin; + const newHeight = width * absSin + height * absCos; + + const newPage = newPdfDoc.addPage([newWidth, newHeight]); + + const x = newWidth / 2 - (width / 2 * Math.cos(angleRad) - height / 2 * Math.sin(angleRad)); + const y = newHeight / 2 - (width / 2 * Math.sin(angleRad) + height / 2 * Math.cos(angleRad)); + + newPage.drawPage(embeddedPage, { + x, + y, + width, + height, + rotate: degrees(totalRotation), + }); + } + } + + const rotatedPdfBytes = await newPdfDoc.save(); + const originalName = pageState.file.name.replace(/\.pdf$/i, ''); + + downloadFile( + new Blob([new Uint8Array(rotatedPdfBytes)], { type: 'application/pdf' }), + `${originalName}_rotated.pdf` + ); + + showAlert('Success', 'Rotations applied successfully!', 'success', function () { + resetState(); + }); + } catch (e) { + console.error(e); + showAlert('Error', 'Could not apply rotations.'); + } finally { + hideLoader(); + } +} + +function handleFileSelect(files: FileList | null) { + if (files && files.length > 0) { + const file = files[0]; + if (file.type === 'application/pdf' || file.name.toLowerCase().endsWith('.pdf')) { + pageState.file = file; + updateUI(); + } + } +} + +document.addEventListener('DOMContentLoaded', function () { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const backBtn = document.getElementById('back-to-tools'); + const batchDecrement = document.getElementById('batch-decrement'); + const batchIncrement = document.getElementById('batch-increment'); + const batchApply = document.getElementById('batch-apply'); + const batchAngleInput = document.getElementById('batch-custom-angle') as HTMLInputElement; + + if (backBtn) { + backBtn.addEventListener('click', function () { + window.location.href = import.meta.env.BASE_URL; + }); + } + + if (batchDecrement && batchAngleInput) { + batchDecrement.addEventListener('click', function () { + const current = parseInt(batchAngleInput.value) || 0; + batchAngleInput.value = (current - 1).toString(); + }); + } + + if (batchIncrement && batchAngleInput) { + batchIncrement.addEventListener('click', function () { + const current = parseInt(batchAngleInput.value) || 0; + batchAngleInput.value = (current + 1).toString(); + }); + } + + if (batchApply && batchAngleInput) { + batchApply.addEventListener('click', function () { + const angle = parseInt(batchAngleInput.value) || 0; + for (let i = 0; i < pageState.rotations.length; i++) { + pageState.rotations[i] = angle; + } + updateAllRotationDisplays(); + }); + } + + if (fileInput && dropZone) { + fileInput.addEventListener('change', function (e) { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', function (e) { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', function (e) { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', function (e) { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const files = e.dataTransfer?.files; + if (files && files.length > 0) { + const pdfFiles = Array.from(files).filter(function (f) { + return f.type === 'application/pdf' || f.name.toLowerCase().endsWith('.pdf'); + }); + if (pdfFiles.length > 0) { + const dataTransfer = new DataTransfer(); + dataTransfer.items.add(pdfFiles[0]); + handleFileSelect(dataTransfer.files); + } + } + }); + + fileInput.addEventListener('click', function () { + fileInput.value = ''; + }); + } + + if (processBtn) { + processBtn.addEventListener('click', applyRotations); + } +}); diff --git a/src/js/logic/rotate-pdf-page.ts b/src/js/logic/rotate-pdf-page.ts index 64b8830..5681fe9 100644 --- a/src/js/logic/rotate-pdf-page.ts +++ b/src/js/logic/rotate-pdf-page.ts @@ -39,19 +39,14 @@ function resetState() { const fileInput = document.getElementById('file-input') as HTMLInputElement; if (fileInput) fileInput.value = ''; - - const batchAngle = document.getElementById('batch-custom-angle') as HTMLInputElement; - if (batchAngle) batchAngle.value = '0'; } function updateAllRotationDisplays() { for (let i = 0; i < pageState.rotations.length; i++) { - const input = document.getElementById(`page-angle-${i}`) as HTMLInputElement; - if (input) input.value = pageState.rotations[i].toString(); const container = document.querySelector(`[data-page-index="${i}"]`); if (container) { const wrapper = container.querySelector('.thumbnail-wrapper') as HTMLElement; - if (wrapper) wrapper.style.transform = `rotate(${-pageState.rotations[i]}deg)`; + if (wrapper) wrapper.style.transform = `rotate(${pageState.rotations[i]}deg)`; } } } @@ -67,6 +62,9 @@ function createPageWrapper(canvas: HTMLCanvasElement, pageNumber: number): HTMLE const canvasWrapper = document.createElement('div'); canvasWrapper.className = 'thumbnail-wrapper flex items-center justify-center p-2 h-36'; canvasWrapper.style.transition = 'transform 0.3s ease'; + // Apply initial rotation if it exists + const initialRotation = pageState.rotations[pageIndex] || 0; + canvasWrapper.style.transform = `rotate(${initialRotation}deg)`; canvas.className = 'max-w-full max-h-full object-contain'; canvasWrapper.appendChild(canvas); @@ -78,49 +76,31 @@ function createPageWrapper(canvas: HTMLCanvasElement, pageNumber: number): HTMLE container.appendChild(canvasWrapper); container.appendChild(pageLabel); - // Per-page rotation controls + // Per-page rotation controls - Left and Right buttons only const controls = document.createElement('div'); - controls.className = 'flex items-center justify-center gap-1 p-2 bg-gray-800'; + controls.className = 'flex items-center justify-center gap-2 p-2 bg-gray-800'; - const decrementBtn = document.createElement('button'); - decrementBtn.className = 'w-8 h-8 flex items-center justify-center bg-gray-700 hover:bg-gray-600 text-white rounded border border-gray-600 text-sm'; - decrementBtn.textContent = '−'; - decrementBtn.onclick = function (e) { + const rotateLeftBtn = document.createElement('button'); + rotateLeftBtn.className = 'flex items-center gap-1 px-3 py-1.5 bg-gray-700 hover:bg-gray-600 text-white rounded border border-gray-600 text-xs'; + rotateLeftBtn.innerHTML = ''; + rotateLeftBtn.onclick = function (e) { e.stopPropagation(); - const input = document.getElementById(`page-angle-${pageIndex}`) as HTMLInputElement; - const current = parseInt(input.value) || 0; - input.value = (current - 1).toString(); - }; - - const angleInput = document.createElement('input'); - angleInput.type = 'number'; - angleInput.id = `page-angle-${pageIndex}`; - angleInput.value = pageState.rotations[pageIndex]?.toString() || '0'; - angleInput.className = 'w-12 h-8 text-center bg-gray-700 border border-gray-600 text-white rounded text-xs'; - - const incrementBtn = document.createElement('button'); - incrementBtn.className = 'w-8 h-8 flex items-center justify-center bg-gray-700 hover:bg-gray-600 text-white rounded border border-gray-600 text-sm'; - incrementBtn.textContent = '+'; - incrementBtn.onclick = function (e) { - e.stopPropagation(); - const input = document.getElementById(`page-angle-${pageIndex}`) as HTMLInputElement; - const current = parseInt(input.value) || 0; - input.value = (current + 1).toString(); - }; - - const applyBtn = document.createElement('button'); - applyBtn.className = 'w-8 h-8 flex items-center justify-center bg-gray-700 hover:bg-gray-600 text-white rounded border border-gray-600'; - applyBtn.innerHTML = ''; - applyBtn.onclick = function (e) { - e.stopPropagation(); - const input = document.getElementById(`page-angle-${pageIndex}`) as HTMLInputElement; - const angle = parseInt(input.value) || 0; - pageState.rotations[pageIndex] = angle; + pageState.rotations[pageIndex] = pageState.rotations[pageIndex] - 90; const wrapper = container.querySelector('.thumbnail-wrapper') as HTMLElement; - if (wrapper) wrapper.style.transform = `rotate(${-angle}deg)`; + if (wrapper) wrapper.style.transform = `rotate(${pageState.rotations[pageIndex]}deg)`; }; - controls.append(decrementBtn, angleInput, incrementBtn, applyBtn); + const rotateRightBtn = document.createElement('button'); + rotateRightBtn.className = 'flex items-center gap-1 px-3 py-1.5 bg-gray-700 hover:bg-gray-600 text-white rounded border border-gray-600 text-xs'; + rotateRightBtn.innerHTML = ''; + rotateRightBtn.onclick = function (e) { + e.stopPropagation(); + pageState.rotations[pageIndex] = pageState.rotations[pageIndex] + 90; + const wrapper = container.querySelector('.thumbnail-wrapper') as HTMLElement; + if (wrapper) wrapper.style.transform = `rotate(${pageState.rotations[pageIndex]}deg)`; + }; + + controls.append(rotateLeftBtn, rotateRightBtn); container.appendChild(controls); // Re-create icons for the new element @@ -240,6 +220,8 @@ async function applyRotations() { const currentRotation = originalPage.getRotation().angle; const totalRotation = currentRotation + rotation; + console.log(`Page ${i}: rotation=${rotation}, currentRotation=${currentRotation}, totalRotation=${totalRotation}, applying=${-totalRotation}`); + if (totalRotation % 90 === 0) { const [copiedPage] = await newPdfDoc.copyPages(pageState.pdfDoc, [i]); copiedPage.setRotation(degrees(totalRotation)); @@ -306,10 +288,6 @@ document.addEventListener('DOMContentLoaded', function () { const backBtn = document.getElementById('back-to-tools'); const rotateAllLeft = document.getElementById('rotate-all-left'); const rotateAllRight = document.getElementById('rotate-all-right'); - const batchDecrement = document.getElementById('batch-decrement'); - const batchIncrement = document.getElementById('batch-increment'); - const batchApply = document.getElementById('batch-apply'); - const batchAngleInput = document.getElementById('batch-custom-angle') as HTMLInputElement; if (backBtn) { backBtn.addEventListener('click', function () { @@ -320,7 +298,7 @@ document.addEventListener('DOMContentLoaded', function () { if (rotateAllLeft) { rotateAllLeft.addEventListener('click', function () { for (let i = 0; i < pageState.rotations.length; i++) { - pageState.rotations[i] = pageState.rotations[i] + 90; + pageState.rotations[i] = pageState.rotations[i] - 90; } updateAllRotationDisplays(); }); @@ -329,38 +307,12 @@ document.addEventListener('DOMContentLoaded', function () { if (rotateAllRight) { rotateAllRight.addEventListener('click', function () { for (let i = 0; i < pageState.rotations.length; i++) { - pageState.rotations[i] = pageState.rotations[i] - 90; + pageState.rotations[i] = pageState.rotations[i] + 90; } updateAllRotationDisplays(); }); } - if (batchDecrement && batchAngleInput) { - batchDecrement.addEventListener('click', function () { - const current = parseInt(batchAngleInput.value) || 0; - batchAngleInput.value = (current - 1).toString(); - }); - } - - if (batchIncrement && batchAngleInput) { - batchIncrement.addEventListener('click', function () { - const current = parseInt(batchAngleInput.value) || 0; - batchAngleInput.value = (current + 1).toString(); - }); - } - - if (batchApply && batchAngleInput) { - batchApply.addEventListener('click', function () { - const angle = parseInt(batchAngleInput.value) || 0; - if (angle !== 0) { - for (let i = 0; i < pageState.rotations.length; i++) { - pageState.rotations[i] = pageState.rotations[i] + angle; - } - updateAllRotationDisplays(); - } - }); - } - if (fileInput && dropZone) { fileInput.addEventListener('change', function (e) { handleFileSelect((e.target as HTMLInputElement).files); diff --git a/src/js/logic/rtf-to-pdf-page.ts b/src/js/logic/rtf-to-pdf-page.ts new file mode 100644 index 0000000..443fc3e --- /dev/null +++ b/src/js/logic/rtf-to-pdf-page.ts @@ -0,0 +1,215 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { + downloadFile, + readFileAsArrayBuffer, + formatBytes, +} from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { getLibreOfficeConverter, type LoadProgress } from '../utils/libreoffice-loader.js'; + +document.addEventListener('DOMContentLoaded', () => { + state.files = []; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const convertOptions = document.getElementById('convert-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const processBtn = document.getElementById('process-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!convertOptions) return; + + if (state.files.length > 0) { + if (fileDisplayArea) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + } + if (fileControls) fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + } else { + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + if (fileControls) fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + state.pdfDoc = null; + updateUI(); + }; + + const convertToPdf = async () => { + try { + if (state.files.length === 0) { + showAlert('No Files', 'Please select at least one RTF file.'); + hideLoader(); + return; + } + + const converter = getLibreOfficeConverter(); + + // Initialize LibreOffice if not already done + await converter.initialize((progress: LoadProgress) => { + showLoader(progress.message, progress.percent); + }); + + if (state.files.length === 1) { + const originalFile = state.files[0]; + + showLoader('Processing...'); + + const pdfBlob = await converter.convertToPdf(originalFile); + + const fileName = originalFile.name.replace(/\.rtf$/i, '') + '.pdf'; + + downloadFile(pdfBlob, fileName); + + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${originalFile.name} to PDF.`, + 'success', + () => resetState() + ); + } else { + showLoader('Converting multiple RTF files to PDF...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.rtf$/i, ''); + const pdfBuffer = await pdfBlob.arrayBuffer(); + zip.file(`${baseName}.pdf`, pdfBuffer); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + + downloadFile(zipBlob, 'rtf-converted.zip'); + + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${state.files.length} RTF file(s) to PDF.`, + 'success', + () => resetState() + ); + } + } catch (e: any) { + hideLoader(); + showAlert( + 'Error', + `An error occurred during conversion. Error: ${e.message}` + ); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + state.files = [...state.files, ...Array.from(files)]; + updateUI(); + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const files = e.dataTransfer?.files; + if (files && files.length > 0) { + const rtfFiles = Array.from(files).filter(f => f.name.toLowerCase().endsWith('.rtf') || f.type === 'text/rtf' || f.type === 'application/rtf'); + if (rtfFiles.length > 0) { + const dataTransfer = new DataTransfer(); + rtfFiles.forEach(f => dataTransfer.items.add(f)); + handleFileSelect(dataTransfer.files); + } + } + }); + + // Clear value on click to allow re-selecting the same file + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => { + fileInput.click(); + }); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', () => { + resetState(); + }); + } + + if (processBtn) { + processBtn.addEventListener('click', convertToPdf); + } + + updateUI(); +}); diff --git a/src/js/logic/sanitize-pdf-page.ts b/src/js/logic/sanitize-pdf-page.ts index 09a6339..170a129 100644 --- a/src/js/logic/sanitize-pdf-page.ts +++ b/src/js/logic/sanitize-pdf-page.ts @@ -2,13 +2,9 @@ import { showAlert } from '../ui.js'; import { downloadFile, formatBytes } from '../utils/helpers.js'; import { PDFDocument, PDFName } from 'pdf-lib'; import { icons, createIcons } from 'lucide'; +import { SanitizePdfState } from '@/types'; -interface PageState { - file: File | null; - pdfDoc: PDFDocument | null; -} - -const pageState: PageState = { +const pageState: SanitizePdfState = { file: null, pdfDoc: null, }; diff --git a/src/js/logic/split-pdf-page.ts b/src/js/logic/split-pdf-page.ts index 774b803..e3a68ac 100644 --- a/src/js/logic/split-pdf-page.ts +++ b/src/js/logic/split-pdf-page.ts @@ -253,8 +253,13 @@ document.addEventListener('DOMContentLoaded', () => { const pageRangeInput = (document.getElementById('page-range') as HTMLInputElement).value; if (!pageRangeInput) throw new Error('Choose a valid page range.'); const ranges = pageRangeInput.split(','); + + const rangeGroups: number[][] = []; for (const range of ranges) { const trimmedRange = range.trim(); + if (!trimmedRange) continue; + + const groupIndices: number[] = []; if (trimmedRange.includes('-')) { const [start, end] = trimmedRange.split('-').map(Number); if ( @@ -265,12 +270,45 @@ document.addEventListener('DOMContentLoaded', () => { start > end ) continue; - for (let i = start; i <= end; i++) indicesToExtract.push(i - 1); + for (let i = start; i <= end; i++) groupIndices.push(i - 1); } else { const pageNum = Number(trimmedRange); if (isNaN(pageNum) || pageNum < 1 || pageNum > totalPages) continue; - indicesToExtract.push(pageNum - 1); + groupIndices.push(pageNum - 1); } + + if (groupIndices.length > 0) { + rangeGroups.push(groupIndices); + indicesToExtract.push(...groupIndices); + } + } + + if (rangeGroups.length > 1) { + showLoader('Creating separate PDFs for each range...'); + const zip = new JSZip(); + + for (let i = 0; i < rangeGroups.length; i++) { + const group = rangeGroups[i]; + const newPdf = await PDFLibDocument.create(); + const copiedPages = await newPdf.copyPages(state.pdfDoc, group); + copiedPages.forEach((page: any) => newPdf.addPage(page)); + const pdfBytes = await newPdf.save(); + + const minPage = Math.min(...group) + 1; + const maxPage = Math.max(...group) + 1; + const filename = minPage === maxPage + ? `page-${minPage}.pdf` + : `pages-${minPage}-${maxPage}.pdf`; + zip.file(filename, pdfBytes); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, 'split-pages.zip'); + hideLoader(); + showAlert('Success', `PDF split into ${rangeGroups.length} files successfully!`, 'success', () => { + resetState(); + }); + return; } break; diff --git a/src/js/logic/text-color-page.ts b/src/js/logic/text-color-page.ts index 955a61e..a471ca7 100644 --- a/src/js/logic/text-color-page.ts +++ b/src/js/logic/text-color-page.ts @@ -3,11 +3,11 @@ import { showAlert, showLoader, hideLoader } from '../ui.js'; import { downloadFile, hexToRgb, formatBytes, getPDFDocument, readFileAsArrayBuffer } from '../utils/helpers.js'; import { PDFDocument as PDFLibDocument } from 'pdf-lib'; import * as pdfjsLib from 'pdfjs-dist'; +import { TextColorState } from '@/types'; pdfjsLib.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString(); -interface PageState { file: File | null; pdfDoc: PDFLibDocument | null; } -const pageState: PageState = { file: null, pdfDoc: null }; +const pageState: TextColorState = { file: null, pdfDoc: null }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initializePage); } else { initializePage(); } diff --git a/src/js/logic/txt-to-pdf-page.ts b/src/js/logic/txt-to-pdf-page.ts index 59e66a4..c8766b0 100644 --- a/src/js/logic/txt-to-pdf-page.ts +++ b/src/js/logic/txt-to-pdf-page.ts @@ -1,25 +1,18 @@ import { showLoader, hideLoader, showAlert } from '../ui.js'; -import { downloadFile, formatBytes, hexToRgb } from '../utils/helpers.js'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; import { createIcons, icons } from 'lucide'; -import { PDFDocument, rgb, StandardFonts, PageSizes } from 'pdf-lib'; -import { getFontForLanguage, getLanguageForChar } from '../utils/font-loader.js'; -import { languageToFontFamily } from '../config/font-mappings.js'; -import fontkit from '@pdf-lib/fontkit'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; let files: File[] = []; let currentMode: 'upload' | 'text' = 'upload'; -let selectedLanguages: string[] = ['eng']; -const allLanguages = Object.keys(languageToFontFamily).sort().map(code => { - let name = code; - try { - const displayNames = new Intl.DisplayNames(['en'], { type: 'language' }); - name = displayNames.of(code) || code; - } catch (e) { - console.warn(`Failed to get language name for ${code}`, e); - } - return { code, name: `${name} (${code})` }; -}); +// RTL character detection pattern (Arabic, Hebrew, Persian, etc.) +const RTL_PATTERN = /[\u0590-\u05FF\u0600-\u06FF\u0700-\u074F\u0750-\u077F\u0780-\u07BF\u07C0-\u07FF\u08A0-\u08FF\uFB1D-\uFB4F\uFB50-\uFDFF\uFE70-\uFEFF]/; + +function hasRtlCharacters(text: string): boolean { + return RTL_PATTERN.test(text); +} const updateUI = () => { const fileDisplayArea = document.getElementById('file-display-area'); @@ -73,140 +66,11 @@ const resetState = () => { updateUI(); }; -async function createPdfFromText( - text: string, - fontSize: number, - pageSizeKey: string, - colorHex: string, - orientation: string, - customWidth?: number, - customHeight?: number -): Promise { - const pdfDoc = await PDFDocument.create(); - pdfDoc.registerFontkit(fontkit); - - const fontMap = new Map(); - const fallbackFont = await pdfDoc.embedFont(StandardFonts.Helvetica); - - if (!selectedLanguages.includes('eng')) { - selectedLanguages.push('eng'); - } - - for (const lang of selectedLanguages) { - try { - const fontBytes = await getFontForLanguage(lang); - const font = await pdfDoc.embedFont(fontBytes, { subset: false }); - fontMap.set(lang, font); - } catch (e) { - console.warn(`Failed to load font for ${lang}, using fallback`, e); - fontMap.set(lang, fallbackFont); - } - } - - let pageSize = pageSizeKey === 'Custom' - ? [customWidth || 595, customHeight || 842] as [number, number] - : (PageSizes as any)[pageSizeKey]; - - if (orientation === 'landscape') { - pageSize = [pageSize[1], pageSize[0]] as [number, number]; - } - - const margin = 72; - const textColor = hexToRgb(colorHex); - - let page = pdfDoc.addPage(pageSize); - let { width, height } = page.getSize(); - const textWidth = width - margin * 2; - const lineHeight = fontSize * 1.3; - let y = height - margin; - - const paragraphs = text.split('\n'); - - for (const paragraph of paragraphs) { - if (paragraph.trim() === '') { - y -= lineHeight; - if (y < margin) { - page = pdfDoc.addPage(pageSize); - y = page.getHeight() - margin; - } - continue; - } - - const words = paragraph.split(' '); - let currentLineWords: { text: string; font: any }[] = []; - let currentLineWidth = 0; - - for (const word of words) { - let wordLang = 'eng'; - - for (const char of word) { - const charLang = getLanguageForChar(char); - if (selectedLanguages.includes(charLang)) { - wordLang = charLang; - break; - } - } - - const font = fontMap.get(wordLang) || fontMap.get('eng') || fallbackFont; - const wordWidth = font.widthOfTextAtSize(word + ' ', fontSize); - - if (currentLineWidth + wordWidth > textWidth && currentLineWords.length > 0) { - currentLineWords.forEach((item, idx) => { - const x = margin + (currentLineWidth * idx / currentLineWords.length); - page.drawText(item.text, { - x: margin + (currentLineWidth - textWidth) / 2, - y: y, - size: fontSize, - font: item.font, - color: rgb(textColor.r / 255, textColor.g / 255, textColor.b / 255), - }); - }); - - currentLineWords = []; - currentLineWidth = 0; - y -= lineHeight; - - if (y < margin) { - page = pdfDoc.addPage(pageSize); - y = page.getHeight() - margin; - } - } - - currentLineWords.push({ text: word + ' ', font }); - currentLineWidth += wordWidth; - } - - if (currentLineWords.length > 0) { - let x = margin; - currentLineWords.forEach((item) => { - page.drawText(item.text, { - x: x, - y: y, - size: fontSize, - font: item.font, - color: rgb(textColor.r / 255, textColor.g / 255, textColor.b / 255), - }); - x += item.font.widthOfTextAtSize(item.text, fontSize); - }); - - y -= lineHeight; - if (y < margin) { - page = pdfDoc.addPage(pageSize); - y = page.getHeight() - margin; - } - } - } - - return await pdfDoc.save(); -} - async function convert() { const fontSize = parseInt((document.getElementById('font-size') as HTMLInputElement).value) || 12; const pageSizeKey = (document.getElementById('page-size') as HTMLSelectElement).value; - const colorHex = (document.getElementById('text-color') as HTMLInputElement).value; - const orientation = (document.getElementById('page-orientation') as HTMLSelectElement).value; - const customWidth = parseInt((document.getElementById('custom-width') as HTMLInputElement)?.value); - const customHeight = parseInt((document.getElementById('custom-height') as HTMLInputElement)?.value); + const fontName = (document.getElementById('font-family') as HTMLSelectElement)?.value || 'helv'; + const textColor = (document.getElementById('text-color') as HTMLInputElement)?.value || '#000000'; if (currentMode === 'upload' && files.length === 0) { showAlert('No Files', 'Please select at least one text file.'); @@ -221,58 +85,59 @@ async function convert() { } } - showLoader('Creating PDF...'); + showLoader('Loading engine...'); + try { + const pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); + await pymupdf.load(); + + let textContent = ''; + if (currentMode === 'upload') { - let combinedText = ''; for (const file of files) { const text = await file.text(); - combinedText += text + '\n\n'; + textContent += text + '\n\n'; } - - const pdfBytes = await createPdfFromText( - combinedText, - fontSize, - pageSizeKey, - colorHex, - orientation, - customWidth, - customHeight - ); - - downloadFile( - new Blob([new Uint8Array(pdfBytes)], { type: 'application/pdf' }), - 'from_text.pdf' - ); } else { const textInput = document.getElementById('text-input') as HTMLTextAreaElement; - const pdfBytes = await createPdfFromText( - textInput.value, - fontSize, - pageSizeKey, - colorHex, - orientation, - customWidth, - customHeight - ); - - downloadFile( - new Blob([new Uint8Array(pdfBytes)], { type: 'application/pdf' }), - 'from_text.pdf' - ); + textContent = textInput.value; } + showLoader('Creating PDF...'); + + const pdfBlob = await pymupdf.textToPdf(textContent, { + fontSize, + pageSize: pageSizeKey as 'a4' | 'letter' | 'legal' | 'a3' | 'a5', + fontName: fontName as 'helv' | 'tiro' | 'cour' | 'times', + textColor, + margins: 72 + }); + + downloadFile(pdfBlob, 'text_to_pdf.pdf'); + showAlert('Success', 'Text converted to PDF successfully!', 'success', () => { resetState(); }); - } catch (e) { - console.error(e); - showAlert('Error', 'Failed to convert text to PDF.'); + } catch (e: any) { + console.error('[TxtToPDF] Error:', e); + showAlert('Error', `Failed to convert text to PDF. ${e.message || ''}`); } finally { hideLoader(); } } +// Update textarea direction based on RTL detection +function updateTextareaDirection(textarea: HTMLTextAreaElement) { + const text = textarea.value; + if (hasRtlCharacters(text)) { + textarea.style.direction = 'rtl'; + textarea.style.textAlign = 'right'; + } else { + textarea.style.direction = 'ltr'; + textarea.style.textAlign = 'left'; + } +} + document.addEventListener('DOMContentLoaded', () => { const fileInput = document.getElementById('file-input') as HTMLInputElement; const dropZone = document.getElementById('drop-zone'); @@ -284,12 +149,7 @@ document.addEventListener('DOMContentLoaded', () => { const textModeBtn = document.getElementById('txt-mode-text-btn'); const uploadPanel = document.getElementById('txt-upload-panel'); const textPanel = document.getElementById('txt-text-panel'); - const pageSizeSelect = document.getElementById('page-size') as HTMLSelectElement; - const customSizeContainer = document.getElementById('custom-size-container'); - const langDropdownBtn = document.getElementById('lang-dropdown-btn'); - const langDropdownContent = document.getElementById('lang-dropdown-content'); - const langSearch = document.getElementById('lang-search') as HTMLInputElement; - const langContainer = document.getElementById('language-list-container'); + const textInput = document.getElementById('text-input') as HTMLTextAreaElement; // Back to Tools if (backBtn) { @@ -321,86 +181,13 @@ document.addEventListener('DOMContentLoaded', () => { }); } - // Custom page size toggle - if (pageSizeSelect && customSizeContainer) { - pageSizeSelect.addEventListener('change', () => { - if (pageSizeSelect.value === 'Custom') { - customSizeContainer.classList.remove('hidden'); - } else { - customSizeContainer.classList.add('hidden'); - } + // RTL auto-detection for textarea + if (textInput) { + textInput.addEventListener('input', () => { + updateTextareaDirection(textInput); }); } - // Language dropdown - if (langDropdownBtn && langDropdownContent && langContainer) { - // Populate language list - allLanguages.forEach(lang => { - const label = document.createElement('label'); - label.className = 'flex items-center gap-2 p-2 hover:bg-gray-700 rounded cursor-pointer'; - - const checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.value = lang.code; - checkbox.className = 'w-4 h-4'; - checkbox.checked = lang.code === 'eng'; - - checkbox.addEventListener('change', () => { - if (checkbox.checked) { - if (!selectedLanguages.includes(lang.code)) { - selectedLanguages.push(lang.code); - } - } else { - selectedLanguages = selectedLanguages.filter(l => l !== lang.code); - } - updateLanguageDisplay(); - }); - - const span = document.createElement('span'); - span.textContent = lang.name; - span.className = 'text-sm text-gray-300'; - - label.append(checkbox, span); - langContainer.appendChild(label); - }); - - langDropdownBtn.addEventListener('click', () => { - langDropdownContent.classList.toggle('hidden'); - }); - - document.addEventListener('click', (e) => { - if (!langDropdownBtn.contains(e.target as Node) && !langDropdownContent.contains(e.target as Node)) { - langDropdownContent.classList.add('hidden'); - } - }); - - if (langSearch) { - langSearch.addEventListener('input', () => { - const searchTerm = langSearch.value.toLowerCase(); - const labels = langContainer.querySelectorAll('label'); - labels.forEach(label => { - const text = label.textContent?.toLowerCase() || ''; - if (text.includes(searchTerm)) { - (label as HTMLElement).style.display = 'flex'; - } else { - (label as HTMLElement).style.display = 'none'; - } - }); - }); - } - } - - function updateLanguageDisplay() { - const langDropdownText = document.getElementById('lang-dropdown-text'); - if (langDropdownText) { - const selectedNames = selectedLanguages.map(code => { - const lang = allLanguages.find(l => l.code === code); - return lang?.name || code; - }); - langDropdownText.textContent = selectedNames.length > 0 ? selectedNames.join(', ') : 'Select Languages'; - } - } - // File handling const handleFileSelect = (newFiles: FileList | null) => { if (!newFiles || newFiles.length === 0) return; diff --git a/src/js/logic/validate-signature-pdf-page.ts b/src/js/logic/validate-signature-pdf-page.ts new file mode 100644 index 0000000..ded88c4 --- /dev/null +++ b/src/js/logic/validate-signature-pdf-page.ts @@ -0,0 +1,469 @@ +import { createIcons, icons } from 'lucide'; +import { showAlert, showLoader, hideLoader } from '../ui.js'; +import { readFileAsArrayBuffer, formatBytes } from '../utils/helpers.js'; +import { validatePdfSignatures } from './validate-signature-pdf.js'; +import forge from 'node-forge'; +import { SignatureValidationResult, ValidateSignatureState } from '@/types'; + +const state: ValidateSignatureState = { + pdfFile: null, + pdfBytes: null, + results: [], + trustedCertFile: null, + trustedCert: null, +}; + +function getElement(id: string): T | null { + return document.getElementById(id) as T | null; +} + +function resetState(): void { + state.pdfFile = null; + state.pdfBytes = null; + state.results = []; + + const fileDisplayArea = getElement('file-display-area'); + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + + const resultsSection = getElement('results-section'); + if (resultsSection) resultsSection.classList.add('hidden'); + + const resultsContainer = getElement('results-container'); + if (resultsContainer) resultsContainer.innerHTML = ''; + + const fileInput = getElement('file-input'); + if (fileInput) fileInput.value = ''; + + const customCertSection = getElement('custom-cert-section'); + if (customCertSection) customCertSection.classList.add('hidden'); +} + +function resetCertState(): void { + state.trustedCertFile = null; + state.trustedCert = null; + + const certDisplayArea = getElement('cert-display-area'); + if (certDisplayArea) certDisplayArea.innerHTML = ''; + + const certInput = getElement('cert-input'); + if (certInput) certInput.value = ''; +} + +function initializePage(): void { + createIcons({ icons }); + + const fileInput = getElement('file-input'); + const dropZone = getElement('drop-zone'); + const backBtn = getElement('back-to-tools'); + const certInput = getElement('cert-input'); + const certDropZone = getElement('cert-drop-zone'); + + if (fileInput) { + fileInput.addEventListener('change', handlePdfUpload); + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (dropZone) { + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', () => { + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const droppedFiles = e.dataTransfer?.files; + if (droppedFiles && droppedFiles.length > 0) { + handlePdfFile(droppedFiles[0]); + } + }); + } + + if (certInput) { + certInput.addEventListener('change', handleCertUpload); + certInput.addEventListener('click', () => { + certInput.value = ''; + }); + } + + if (certDropZone) { + certDropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + certDropZone.classList.add('bg-gray-700'); + }); + + certDropZone.addEventListener('dragleave', () => { + certDropZone.classList.remove('bg-gray-700'); + }); + + certDropZone.addEventListener('drop', (e) => { + e.preventDefault(); + certDropZone.classList.remove('bg-gray-700'); + const droppedFiles = e.dataTransfer?.files; + if (droppedFiles && droppedFiles.length > 0) { + handleCertFile(droppedFiles[0]); + } + }); + } + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } +} + +function handlePdfUpload(e: Event): void { + const input = e.target as HTMLInputElement; + if (input.files && input.files.length > 0) { + handlePdfFile(input.files[0]); + } +} + +async function handlePdfFile(file: File): Promise { + if (file.type !== 'application/pdf' && !file.name.toLowerCase().endsWith('.pdf')) { + showAlert('Invalid File', 'Please select a PDF file.'); + return; + } + + resetState(); + state.pdfFile = file; + state.pdfBytes = new Uint8Array(await readFileAsArrayBuffer(file) as ArrayBuffer); + + updatePdfDisplay(); + + const customCertSection = getElement('custom-cert-section'); + if (customCertSection) customCertSection.classList.remove('hidden'); + createIcons({ icons }); + + await validateSignatures(); +} + +function updatePdfDisplay(): void { + const fileDisplayArea = getElement('file-display-area'); + if (!fileDisplayArea || !state.pdfFile) return; + + fileDisplayArea.innerHTML = ''; + + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col flex-1 min-w-0'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = state.pdfFile.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(state.pdfFile.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => resetState(); + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + createIcons({ icons }); +} + +function handleCertUpload(e: Event): void { + const input = e.target as HTMLInputElement; + if (input.files && input.files.length > 0) { + handleCertFile(input.files[0]); + } +} + +async function handleCertFile(file: File): Promise { + const validExtensions = ['.pem', '.crt', '.cer', '.der']; + const hasValidExtension = validExtensions.some(ext => file.name.toLowerCase().endsWith(ext)); + + if (!hasValidExtension) { + showAlert('Invalid Certificate', 'Please select a .pem, .crt, .cer, or .der certificate file.'); + return; + } + + resetCertState(); + state.trustedCertFile = file; + + try { + const content = await file.text(); + + if (content.includes('-----BEGIN CERTIFICATE-----')) { + state.trustedCert = forge.pki.certificateFromPem(content); + } else { + const bytes = new Uint8Array(await readFileAsArrayBuffer(file) as ArrayBuffer); + const derString = String.fromCharCode.apply(null, Array.from(bytes)); + const asn1 = forge.asn1.fromDer(derString); + state.trustedCert = forge.pki.certificateFromAsn1(asn1); + } + + updateCertDisplay(); + + if (state.pdfBytes) { + await validateSignatures(); + } + } catch (error) { + console.error('Error parsing certificate:', error); + showAlert('Invalid Certificate', 'Failed to parse the certificate file.'); + resetCertState(); + } +} + +function updateCertDisplay(): void { + const certDisplayArea = getElement('cert-display-area'); + if (!certDisplayArea || !state.trustedCertFile || !state.trustedCert) return; + + certDisplayArea.innerHTML = ''; + + const certDiv = document.createElement('div'); + certDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col flex-1 min-w-0'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + + const cn = state.trustedCert.subject.getField('CN'); + nameSpan.textContent = cn?.value as string || state.trustedCertFile.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-green-400'; + metaSpan.innerHTML = 'Trusted certificate loaded'; + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = async () => { + resetCertState(); + if (state.pdfBytes) { + await validateSignatures(); + } + }; + + certDiv.append(infoContainer, removeBtn); + certDisplayArea.appendChild(certDiv); + createIcons({ icons }); +} + +async function validateSignatures(): Promise { + if (!state.pdfBytes) return; + + showLoader('Analyzing signatures...'); + + try { + state.results = await validatePdfSignatures(state.pdfBytes, state.trustedCert ?? undefined); + displayResults(); + } catch (error) { + console.error('Validation error:', error); + showAlert('Error', 'Failed to validate signatures. The file may be corrupted.'); + } finally { + hideLoader(); + } +} + +function displayResults(): void { + const resultsSection = getElement('results-section'); + const resultsContainer = getElement('results-container'); + + if (!resultsSection || !resultsContainer) return; + + resultsContainer.innerHTML = ''; + resultsSection.classList.remove('hidden'); + + if (state.results.length === 0) { + resultsContainer.innerHTML = ` +
+ +

No Signatures Found

+

This PDF does not contain any digital signatures.

+
+ `; + createIcons({ icons }); + return; + } + + const summaryDiv = document.createElement('div'); + summaryDiv.className = 'mb-4 p-3 bg-gray-700 rounded-lg border border-gray-600'; + + const validCount = state.results.filter(r => r.isValid && !r.isExpired).length; + const trustVerified = state.trustedCert ? state.results.filter(r => r.isTrusted).length : 0; + + let summaryHtml = ` +

+ ${state.results.length} + signature${state.results.length > 1 ? 's' : ''} found + + ${validCount} valid +

+ `; + + if (state.trustedCert) { + summaryHtml += ` +

+ + Trust verification: ${trustVerified}/${state.results.length} signatures verified against custom certificate +

+ `; + } + + summaryDiv.innerHTML = summaryHtml; + resultsContainer.appendChild(summaryDiv); + + state.results.forEach((result, index) => { + const card = createSignatureCard(result, index); + resultsContainer.appendChild(card); + }); + + createIcons({ icons }); +} + +function createSignatureCard(result: SignatureValidationResult, index: number): HTMLElement { + const card = document.createElement('div'); + card.className = 'bg-gray-700 rounded-lg p-4 border border-gray-600 mb-4'; + + let statusColor = 'text-green-400'; + let statusIcon = 'check-circle'; + let statusText = 'Valid Signature'; + + if (!result.isValid) { + statusColor = 'text-red-400'; + statusIcon = 'x-circle'; + statusText = 'Invalid Signature'; + } else if (result.isExpired) { + statusColor = 'text-yellow-400'; + statusIcon = 'alert-triangle'; + statusText = 'Certificate Expired'; + } else if (result.isSelfSigned) { + statusColor = 'text-yellow-400'; + statusIcon = 'alert-triangle'; + statusText = 'Self-Signed Certificate'; + } + + const formatDate = (date: Date) => { + if (!date || date.getTime() === 0) return 'Unknown'; + return date.toLocaleDateString(undefined, { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); + }; + + let trustBadge = ''; + if (state.trustedCert) { + if (result.isTrusted) { + trustBadge = 'Trusted'; + } else { + trustBadge = 'Not in trust chain'; + } + } + + card.innerHTML = ` +
+
+ +
+

Signature ${index + 1}

+

${statusText}

+
+
+
+ ${result.coverageStatus === 'full' + ? 'Full Coverage' + : result.coverageStatus === 'partial' + ? 'Partial Coverage' + : '' + }${trustBadge} +
+
+ +
+
+
+

Signed By

+

${escapeHtml(result.signerName)}

+ ${result.signerOrg ? `

${escapeHtml(result.signerOrg)}

` : ''} + ${result.signerEmail ? `

${escapeHtml(result.signerEmail)}

` : ''} +
+
+

Issuer

+

${escapeHtml(result.issuer)}

+ ${result.issuerOrg ? `

${escapeHtml(result.issuerOrg)}

` : ''} +
+
+ + ${result.signatureDate ? ` +
+

Signed On

+

${formatDate(result.signatureDate)}

+
+ ` : ''} + +
+
+

Valid From

+

${formatDate(result.validFrom)}

+
+
+

Valid Until

+

${formatDate(result.validTo)}

+
+
+ + ${result.reason ? ` +
+

Reason

+

${escapeHtml(result.reason)}

+
+ ` : ''} + + ${result.location ? ` +
+

Location

+

${escapeHtml(result.location)}

+
+ ` : ''} + +
+ + Technical Details + +
+

Serial Number: ${escapeHtml(result.serialNumber)}

+

Digest Algorithm: ${escapeHtml(result.algorithms.digest)}

+

Signature Algorithm: ${escapeHtml(result.algorithms.signature)}

+ ${result.errorMessage ? `

Error: ${escapeHtml(result.errorMessage)}

` : ''} +
+
+
+ `; + + return card; +} + +function escapeHtml(str: string): string { + const div = document.createElement('div'); + div.textContent = str; + return div.innerHTML; +} + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initializePage); +} else { + initializePage(); +} diff --git a/src/js/logic/validate-signature-pdf.ts b/src/js/logic/validate-signature-pdf.ts new file mode 100644 index 0000000..59ee5f5 --- /dev/null +++ b/src/js/logic/validate-signature-pdf.ts @@ -0,0 +1,238 @@ +import forge from 'node-forge'; +import { ExtractedSignature, SignatureValidationResult } from '@/types'; + + +export function extractSignatures(pdfBytes: Uint8Array): ExtractedSignature[] { + const signatures: ExtractedSignature[] = []; + const pdfString = new TextDecoder('latin1').decode(pdfBytes); + + // Find all signature objects for /Type /Sig + const sigRegex = /\/Type\s*\/Sig\b/g; + let sigMatch; + let sigIndex = 0; + + while ((sigMatch = sigRegex.exec(pdfString)) !== null) { + try { + const searchStart = Math.max(0, sigMatch.index - 5000); + const searchEnd = Math.min(pdfString.length, sigMatch.index + 10000); + const context = pdfString.substring(searchStart, searchEnd); + const byteRangeMatch = context.match(/\/ByteRange\s*\[\s*(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s*\]/); + if (!byteRangeMatch) continue; + + const byteRange = [ + parseInt(byteRangeMatch[1], 10), + parseInt(byteRangeMatch[2], 10), + parseInt(byteRangeMatch[3], 10), + parseInt(byteRangeMatch[4], 10), + ]; + + const contentsMatch = context.match(/\/Contents\s*<([0-9A-Fa-f]+)>/); + if (!contentsMatch) continue; + + const hexContents = contentsMatch[1]; + const contentsBytes = hexToBytes(hexContents); + + const reasonMatch = context.match(/\/Reason\s*\(([^)]*)\)/); + const locationMatch = context.match(/\/Location\s*\(([^)]*)\)/); + const contactMatch = context.match(/\/ContactInfo\s*\(([^)]*)\)/); + const nameMatch = context.match(/\/Name\s*\(([^)]*)\)/); + const timeMatch = context.match(/\/M\s*\(D:(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/); + + let signingTime: string | undefined; + if (timeMatch) { + signingTime = `${timeMatch[1]}-${timeMatch[2]}-${timeMatch[3]}T${timeMatch[4]}:${timeMatch[5]}:${timeMatch[6]}`; + } + + signatures.push({ + index: sigIndex++, + contents: contentsBytes, + byteRange, + reason: reasonMatch ? decodeURIComponent(escape(reasonMatch[1])) : undefined, + location: locationMatch ? decodeURIComponent(escape(locationMatch[1])) : undefined, + contactInfo: contactMatch ? decodeURIComponent(escape(contactMatch[1])) : undefined, + name: nameMatch ? decodeURIComponent(escape(nameMatch[1])) : undefined, + signingTime, + }); + } catch (e) { + console.warn('Error extracting signature at index', sigIndex, e); + } + } + + return signatures; +} + +export function validateSignature( + signature: ExtractedSignature, + pdfBytes: Uint8Array, + trustedCert?: forge.pki.Certificate +): SignatureValidationResult { + const result: SignatureValidationResult = { + signatureIndex: signature.index, + isValid: false, + signerName: 'Unknown', + issuer: 'Unknown', + validFrom: new Date(0), + validTo: new Date(0), + isExpired: false, + isSelfSigned: false, + isTrusted: false, + algorithms: { digest: 'Unknown', signature: 'Unknown' }, + serialNumber: '', + byteRange: signature.byteRange, + coverageStatus: 'unknown', + reason: signature.reason, + location: signature.location, + contactInfo: signature.contactInfo, + }; + + try { + const binaryString = String.fromCharCode.apply(null, Array.from(signature.contents)); + const asn1 = forge.asn1.fromDer(binaryString); + const p7 = forge.pkcs7.messageFromAsn1(asn1) as any; + + if (!p7.certificates || p7.certificates.length === 0) { + result.errorMessage = 'No certificates found in signature'; + return result; + } + + const signerCert = p7.certificates[0] as forge.pki.Certificate; + + const subjectCN = signerCert.subject.getField('CN'); + const subjectO = signerCert.subject.getField('O'); + const subjectE = signerCert.subject.getField('E') || signerCert.subject.getField('emailAddress'); + const issuerCN = signerCert.issuer.getField('CN'); + const issuerO = signerCert.issuer.getField('O'); + + result.signerName = (subjectCN?.value as string) ?? 'Unknown'; + result.signerOrg = subjectO?.value as string | undefined; + result.signerEmail = subjectE?.value as string | undefined; + result.issuer = (issuerCN?.value as string) ?? 'Unknown'; + result.issuerOrg = issuerO?.value as string | undefined; + result.validFrom = signerCert.validity.notBefore; + result.validTo = signerCert.validity.notAfter; + result.serialNumber = signerCert.serialNumber; + + const now = new Date(); + result.isExpired = now > result.validTo || now < result.validFrom; + + result.isSelfSigned = signerCert.isIssuer(signerCert); + + // Check trust against provided certificate + if (trustedCert) { + try { + const isTrustedIssuer = trustedCert.isIssuer(signerCert); + const isSameCert = signerCert.serialNumber === trustedCert.serialNumber; + + let chainTrusted = false; + for (const cert of p7.certificates) { + if (trustedCert.isIssuer(cert) || + (cert as forge.pki.Certificate).serialNumber === trustedCert.serialNumber) { + chainTrusted = true; + break; + } + } + + result.isTrusted = isTrustedIssuer || isSameCert || chainTrusted; + } catch { + result.isTrusted = false; + } + } + + result.algorithms = { + digest: getDigestAlgorithmName(signerCert.siginfo?.algorithmOid || ''), + signature: getSignatureAlgorithmName(signerCert.signatureOid || ''), + }; + + // Parse signing time if available in signature + if (signature.signingTime) { + result.signatureDate = new Date(signature.signingTime); + } else { + // Try to extract from authenticated attributes + try { + const signedData = p7 as any; + if (signedData.rawCapture?.authenticatedAttributes) { + // Look for signing time attribute + for (const attr of signedData.rawCapture.authenticatedAttributes) { + if (attr.type === forge.pki.oids.signingTime) { + result.signatureDate = attr.value; + break; + } + } + } + } catch { /* ignore */ } + } + + if (signature.byteRange && signature.byteRange.length === 4) { + const [start1, len1, start2, len2] = signature.byteRange; + const totalCovered = len1 + len2; + const expectedEnd = start2 + len2; + + if (expectedEnd === pdfBytes.length) { + result.coverageStatus = 'full'; + } else if (expectedEnd < pdfBytes.length) { + result.coverageStatus = 'partial'; + } + } + + result.isValid = true; + + } catch (e) { + result.errorMessage = e instanceof Error ? e.message : 'Failed to parse signature'; + } + + return result; +} + +export async function validatePdfSignatures( + pdfBytes: Uint8Array, + trustedCert?: forge.pki.Certificate +): Promise { + const signatures = extractSignatures(pdfBytes); + return signatures.map(sig => validateSignature(sig, pdfBytes, trustedCert)); +} + +export function countSignatures(pdfBytes: Uint8Array): number { + return extractSignatures(pdfBytes).length; +} + +function hexToBytes(hex: string): Uint8Array { + const bytes = new Uint8Array(hex.length / 2); + for (let i = 0; i < hex.length; i += 2) { + bytes[i / 2] = parseInt(hex.substr(i, 2), 16); + } + + let actualLength = bytes.length; + while (actualLength > 0 && bytes[actualLength - 1] === 0) { + actualLength--; + } + + return bytes.slice(0, actualLength); +} + +function getDigestAlgorithmName(oid: string): string { + const digestAlgorithms: Record = { + '1.2.840.113549.2.5': 'MD5', + '1.3.14.3.2.26': 'SHA-1', + '2.16.840.1.101.3.4.2.1': 'SHA-256', + '2.16.840.1.101.3.4.2.2': 'SHA-384', + '2.16.840.1.101.3.4.2.3': 'SHA-512', + '2.16.840.1.101.3.4.2.4': 'SHA-224', + }; + return digestAlgorithms[oid] || oid || 'Unknown'; +} + +function getSignatureAlgorithmName(oid: string): string { + const signatureAlgorithms: Record = { + '1.2.840.113549.1.1.1': 'RSA', + '1.2.840.113549.1.1.5': 'RSA with SHA-1', + '1.2.840.113549.1.1.11': 'RSA with SHA-256', + '1.2.840.113549.1.1.12': 'RSA with SHA-384', + '1.2.840.113549.1.1.13': 'RSA with SHA-512', + '1.2.840.10045.2.1': 'ECDSA', + '1.2.840.10045.4.1': 'ECDSA with SHA-1', + '1.2.840.10045.4.3.2': 'ECDSA with SHA-256', + '1.2.840.10045.4.3.3': 'ECDSA with SHA-384', + '1.2.840.10045.4.3.4': 'ECDSA with SHA-512', + }; + return signatureAlgorithms[oid] || oid || 'Unknown'; +} diff --git a/src/js/logic/view-metadata-page.ts b/src/js/logic/view-metadata-page.ts index fc00e66..240dcce 100644 --- a/src/js/logic/view-metadata-page.ts +++ b/src/js/logic/view-metadata-page.ts @@ -1,11 +1,7 @@ import { showLoader, hideLoader, showAlert } from '../ui.js'; import { formatBytes, formatIsoDate, getPDFDocument } from '../utils/helpers.js'; import { createIcons, icons } from 'lucide'; - -interface ViewMetadataState { - file: File | null; - metadata: Record; -} +import { ViewMetadataState } from '@/types'; const pageState: ViewMetadataState = { file: null, diff --git a/src/js/logic/vsd-to-pdf-page.ts b/src/js/logic/vsd-to-pdf-page.ts new file mode 100644 index 0000000..01430d6 --- /dev/null +++ b/src/js/logic/vsd-to-pdf-page.ts @@ -0,0 +1,142 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { getLibreOfficeConverter, type LoadProgress } from '../utils/libreoffice-loader.js'; + +const ACCEPTED_EXTENSIONS = ['.vsd', '.vsdx']; +const FILETYPE_NAME = 'VSD'; + +document.addEventListener('DOMContentLoaded', () => { + state.files = []; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const convertOptions = document.getElementById('convert-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const processBtn = document.getElementById('process-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!convertOptions) return; + + if (state.files.length > 0) { + if (fileDisplayArea) { + fileDisplayArea.innerHTML = ''; + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + infoContainer.append(nameSpan, metaSpan); + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + createIcons({ icons }); + } + if (fileControls) fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + } else { + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + if (fileControls) fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + updateUI(); + }; + + const convert = async () => { + if (state.files.length === 0) { + showAlert('No Files', `Please select at least one ${FILETYPE_NAME} file.`); + return; + } + try { + const converter = getLibreOfficeConverter(); + showLoader('Loading engine...'); + await converter.initialize((progress: LoadProgress) => { + showLoader(progress.message, progress.percent); + }); + if (state.files.length === 1) { + const file = state.files[0]; + showLoader(`Converting ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + const baseName = file.name.replace(/\.[^/.]+$/, ''); + downloadFile(pdfBlob, `${baseName}.pdf`); + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${file.name} to PDF.`, 'success', () => resetState()); + } else { + showLoader('Converting multiple files...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + const baseName = file.name.replace(/\.[^/.]+$/, ''); + zip.file(`${baseName}.pdf`, pdfBlob); + } + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, `${FILETYPE_NAME.toLowerCase()}-to-pdf.zip`); + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${state.files.length} files to PDF.`, 'success', () => resetState()); + } + } catch (err) { + hideLoader(); + const message = err instanceof Error ? err.message : 'Unknown error'; + console.error(`[${FILETYPE_NAME}ToPDF] Error:`, err); + showAlert('Error', `An error occurred during conversion. Error: ${message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(file => { + const ext = '.' + file.name.split('.').pop()?.toLowerCase(); + return ACCEPTED_EXTENSIONS.includes(ext); + }); + if (validFiles.length > 0) { + state.files = [...state.files, ...validFiles]; + updateUI(); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => handleFileSelect((e.target as HTMLInputElement).files)); + dropZone.addEventListener('dragover', (e) => { e.preventDefault(); dropZone.classList.add('bg-gray-700'); }); + dropZone.addEventListener('dragleave', (e) => { e.preventDefault(); dropZone.classList.remove('bg-gray-700'); }); + dropZone.addEventListener('drop', (e) => { e.preventDefault(); dropZone.classList.remove('bg-gray-700'); handleFileSelect(e.dataTransfer?.files ?? null); }); + fileInput.addEventListener('click', () => { fileInput.value = ''; }); + } + if (addMoreBtn) addMoreBtn.addEventListener('click', () => fileInput.click()); + if (clearFilesBtn) clearFilesBtn.addEventListener('click', resetState); + if (processBtn) processBtn.addEventListener('click', convert); + + updateUI(); +}); diff --git a/src/js/logic/word-to-pdf-page.ts b/src/js/logic/word-to-pdf-page.ts new file mode 100644 index 0000000..e198e3b --- /dev/null +++ b/src/js/logic/word-to-pdf-page.ts @@ -0,0 +1,236 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { + downloadFile, + readFileAsArrayBuffer, + formatBytes, +} from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { getLibreOfficeConverter, type LoadProgress } from '../utils/libreoffice-loader.js'; + +document.addEventListener('DOMContentLoaded', () => { + state.files = []; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const convertOptions = document.getElementById('convert-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const processBtn = document.getElementById('process-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!convertOptions) return; + + if (state.files.length > 0) { + if (fileDisplayArea) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + } + if (fileControls) fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + } else { + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + if (fileControls) fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + state.pdfDoc = null; + updateUI(); + }; + + const convertToPdf = async () => { + try { + console.log('[Word2PDF] Starting conversion...'); + console.log('[Word2PDF] Number of files:', state.files.length); + + if (state.files.length === 0) { + showAlert('No Files', 'Please select at least one Word document.'); + hideLoader(); + return; + } + + const converter = getLibreOfficeConverter(); + console.log('[Word2PDF] Got converter instance'); + + // Initialize LibreOffice if not already done + console.log('[Word2PDF] Initializing LibreOffice...'); + await converter.initialize((progress: LoadProgress) => { + console.log('[Word2PDF] Init progress:', progress.percent + '%', progress.message); + showLoader(progress.message, progress.percent); + }); + console.log('[Word2PDF] LibreOffice initialized successfully!'); + + if (state.files.length === 1) { + const originalFile = state.files[0]; + console.log('[Word2PDF] Converting single file:', originalFile.name); + + showLoader('Processing...'); + + const pdfBlob = await converter.convertToPdf(originalFile); + console.log('[Word2PDF] Conversion complete! PDF size:', pdfBlob.size); + + const fileName = originalFile.name.replace(/\.(doc|docx|odt|rtf)$/i, '') + '.pdf'; + + downloadFile(pdfBlob, fileName); + console.log('[Word2PDF] File downloaded:', fileName); + + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${originalFile.name} to PDF.`, + 'success', + () => resetState() + ); + } else { + console.log('[Word2PDF] Converting multiple files:', state.files.length); + showLoader('Processing...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + console.log(`[Word2PDF] Converting file ${i + 1}/${state.files.length}:`, file.name); + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + + const pdfBlob = await converter.convertToPdf(file); + console.log(`[Word2PDF] Converted ${file.name}, PDF size:`, pdfBlob.size); + + const baseName = file.name.replace(/\.(doc|docx|odt|rtf)$/i, ''); + const pdfBuffer = await pdfBlob.arrayBuffer(); + zip.file(`${baseName}.pdf`, pdfBuffer); + } + + console.log('[Word2PDF] Generating ZIP file...'); + const zipBlob = await zip.generateAsync({ type: 'blob' }); + console.log('[Word2PDF] ZIP size:', zipBlob.size); + + downloadFile(zipBlob, 'word-converted.zip'); + + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${state.files.length} Word document(s) to PDF.`, + 'success', + () => resetState() + ); + } + } catch (e: any) { + console.error('[Word2PDF] ERROR:', e); + console.error('[Word2PDF] Error stack:', e.stack); + hideLoader(); + showAlert( + 'Error', + `An error occurred during conversion. Error: ${e.message}` + ); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + state.files = [...state.files, ...Array.from(files)]; + updateUI(); + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const files = e.dataTransfer?.files; + if (files && files.length > 0) { + const wordFiles = Array.from(files).filter(f => { + const name = f.name.toLowerCase(); + return name.endsWith('.doc') || name.endsWith('.docx') || name.endsWith('.odt') || name.endsWith('.rtf'); + }); + if (wordFiles.length > 0) { + const dataTransfer = new DataTransfer(); + wordFiles.forEach(f => dataTransfer.items.add(f)); + handleFileSelect(dataTransfer.files); + } + } + }); + + // Clear value on click to allow re-selecting the same file + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => { + fileInput.click(); + }); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', () => { + resetState(); + }); + } + + if (processBtn) { + processBtn.addEventListener('click', convertToPdf); + } + + // Initialize UI state (ensures button is hidden when no files) + updateUI(); +}); diff --git a/src/js/logic/wpd-to-pdf-page.ts b/src/js/logic/wpd-to-pdf-page.ts new file mode 100644 index 0000000..9d41536 --- /dev/null +++ b/src/js/logic/wpd-to-pdf-page.ts @@ -0,0 +1,188 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { + downloadFile, + formatBytes, +} from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { getLibreOfficeConverter, type LoadProgress } from '../utils/libreoffice-loader.js'; + +const ACCEPTED_EXTENSIONS = ['.wpd']; +const FILETYPE_NAME = 'WPD'; + +document.addEventListener('DOMContentLoaded', () => { + state.files = []; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const convertOptions = document.getElementById('convert-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const processBtn = document.getElementById('process-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!convertOptions) return; + + if (state.files.length > 0) { + if (fileDisplayArea) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + } + if (fileControls) fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + } else { + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + if (fileControls) fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + updateUI(); + }; + + const convert = async () => { + if (state.files.length === 0) { + showAlert('No Files', `Please select at least one ${FILETYPE_NAME} file.`); + return; + } + + try { + const converter = getLibreOfficeConverter(); + + showLoader('Loading engine...'); + await converter.initialize((progress: LoadProgress) => { + showLoader(progress.message, progress.percent); + }); + + if (state.files.length === 1) { + const file = state.files[0]; + showLoader(`Converting ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + downloadFile(pdfBlob, `${baseName}.pdf`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${file.name} to PDF.`, 'success', () => resetState()); + } else { + showLoader('Converting multiple files...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + zip.file(`${baseName}.pdf`, pdfBlob); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, `${FILETYPE_NAME.toLowerCase()}-to-pdf.zip`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${state.files.length} files to PDF.`, 'success', () => resetState()); + } + } catch (e: any) { + hideLoader(); + console.error(`[${FILETYPE_NAME}ToPDF] Error:`, e); + showAlert('Error', `An error occurred during conversion. Error: ${e.message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(file => { + const ext = '.' + file.name.split('.').pop()?.toLowerCase(); + return ACCEPTED_EXTENSIONS.includes(ext); + }); + if (validFiles.length > 0) { + state.files = [...state.files, ...validFiles]; + updateUI(); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => fileInput.click()); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', resetState); + } + + if (processBtn) { + processBtn.addEventListener('click', convert); + } + + updateUI(); +}); diff --git a/src/js/logic/wps-to-pdf-page.ts b/src/js/logic/wps-to-pdf-page.ts new file mode 100644 index 0000000..641bae2 --- /dev/null +++ b/src/js/logic/wps-to-pdf-page.ts @@ -0,0 +1,188 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { + downloadFile, + formatBytes, +} from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { getLibreOfficeConverter, type LoadProgress } from '../utils/libreoffice-loader.js'; + +const ACCEPTED_EXTENSIONS = ['.wps']; +const FILETYPE_NAME = 'WPS'; + +document.addEventListener('DOMContentLoaded', () => { + state.files = []; + + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const convertOptions = document.getElementById('convert-options'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + const processBtn = document.getElementById('process-btn'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!convertOptions) return; + + if (state.files.length > 0) { + if (fileDisplayArea) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + } + if (fileControls) fileControls.classList.remove('hidden'); + convertOptions.classList.remove('hidden'); + } else { + if (fileDisplayArea) fileDisplayArea.innerHTML = ''; + if (fileControls) fileControls.classList.add('hidden'); + convertOptions.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + updateUI(); + }; + + const convert = async () => { + if (state.files.length === 0) { + showAlert('No Files', `Please select at least one ${FILETYPE_NAME} file.`); + return; + } + + try { + const converter = getLibreOfficeConverter(); + + showLoader('Loading engine...'); + await converter.initialize((progress: LoadProgress) => { + showLoader(progress.message, progress.percent); + }); + + if (state.files.length === 1) { + const file = state.files[0]; + showLoader(`Converting ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + downloadFile(pdfBlob, `${baseName}.pdf`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${file.name} to PDF.`, 'success', () => resetState()); + } else { + showLoader('Converting multiple files...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + const pdfBlob = await converter.convertToPdf(file); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + zip.file(`${baseName}.pdf`, pdfBlob); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, `${FILETYPE_NAME.toLowerCase()}-to-pdf.zip`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${state.files.length} files to PDF.`, 'success', () => resetState()); + } + } catch (e: any) { + hideLoader(); + console.error(`[${FILETYPE_NAME}ToPDF] Error:`, e); + showAlert('Error', `An error occurred during conversion. Error: ${e.message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(file => { + const ext = '.' + file.name.split('.').pop()?.toLowerCase(); + return ACCEPTED_EXTENSIONS.includes(ext); + }); + if (validFiles.length > 0) { + state.files = [...state.files, ...validFiles]; + updateUI(); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => fileInput.click()); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', resetState); + } + + if (processBtn) { + processBtn.addEventListener('click', convert); + } + + updateUI(); +}); diff --git a/src/js/logic/xml-to-pdf-page.ts b/src/js/logic/xml-to-pdf-page.ts new file mode 100644 index 0000000..382ab5a --- /dev/null +++ b/src/js/logic/xml-to-pdf-page.ts @@ -0,0 +1,181 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { + downloadFile, + formatBytes, +} from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { convertXmlToPdf } from '../utils/xml-to-pdf.js'; + +const ACCEPTED_EXTENSIONS = ['.xml']; +const FILETYPE_NAME = 'XML'; + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!fileDisplayArea || !processBtn || !fileControls) return; + + if (state.files.length > 0) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + fileControls.classList.remove('hidden'); + processBtn.classList.remove('hidden'); + } else { + fileDisplayArea.innerHTML = ''; + fileControls.classList.add('hidden'); + processBtn.classList.add('hidden'); + } + }; + + const resetState = () => { + state.files = []; + updateUI(); + }; + + const convert = async () => { + if (state.files.length === 0) { + showAlert('No Files', `Please select at least one ${FILETYPE_NAME} file.`); + return; + } + + try { + if (state.files.length === 1) { + const file = state.files[0]; + const pdfBlob = await convertXmlToPdf(file, { + onProgress: (percent, message) => { + showLoader(message, percent); + } + }); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + downloadFile(pdfBlob, `${baseName}.pdf`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${file.name} to PDF.`, 'success', () => resetState()); + } else { + showLoader('Converting multiple files...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + const pdfBlob = await convertXmlToPdf(file, { + onProgress: (percent, message) => { + showLoader(`File ${i + 1}/${state.files.length}: ${message}`, percent); + } + }); + + const baseName = file.name.replace(/\.[^/.]+$/, ''); + zip.file(`${baseName}.pdf`, pdfBlob); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, `${FILETYPE_NAME.toLowerCase()}-to-pdf.zip`); + + hideLoader(); + showAlert('Conversion Complete', `Successfully converted ${state.files.length} files to PDF.`, 'success', () => resetState()); + } + } catch (err) { + hideLoader(); + const message = err instanceof Error ? err.message : 'Unknown error'; + console.error(`[${FILETYPE_NAME}ToPDF] Error:`, err); + showAlert('Error', `An error occurred during conversion. Error: ${message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(file => { + const ext = '.' + file.name.split('.').pop()?.toLowerCase(); + return ACCEPTED_EXTENSIONS.includes(ext); + }); + if (validFiles.length > 0) { + state.files = [...state.files, ...validFiles]; + updateUI(); + } + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + handleFileSelect(e.dataTransfer?.files ?? null); + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => fileInput.click()); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', resetState); + } + + if (processBtn) { + processBtn.addEventListener('click', convert); + } +}); diff --git a/src/js/logic/xps-to-pdf-page.ts b/src/js/logic/xps-to-pdf-page.ts new file mode 100644 index 0000000..f3af175 --- /dev/null +++ b/src/js/logic/xps-to-pdf-page.ts @@ -0,0 +1,202 @@ +import { showLoader, hideLoader, showAlert } from '../ui.js'; +import { downloadFile, formatBytes } from '../utils/helpers.js'; +import { state } from '../state.js'; +import { createIcons, icons } from 'lucide'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +const FILETYPE = 'xps'; +const EXTENSIONS = ['.xps', '.oxps']; +const TOOL_NAME = 'XPS'; + +document.addEventListener('DOMContentLoaded', () => { + const fileInput = document.getElementById('file-input') as HTMLInputElement; + const dropZone = document.getElementById('drop-zone'); + const processBtn = document.getElementById('process-btn'); + const fileDisplayArea = document.getElementById('file-display-area'); + const fileControls = document.getElementById('file-controls'); + const addMoreBtn = document.getElementById('add-more-btn'); + const clearFilesBtn = document.getElementById('clear-files-btn'); + const backBtn = document.getElementById('back-to-tools'); + + if (backBtn) { + backBtn.addEventListener('click', () => { + window.location.href = import.meta.env.BASE_URL; + }); + } + + const updateUI = async () => { + if (!fileDisplayArea || !processBtn || !fileControls) return; + + if (state.files.length > 0) { + fileDisplayArea.innerHTML = ''; + + for (let index = 0; index < state.files.length; index++) { + const file = state.files[index]; + const fileDiv = document.createElement('div'); + fileDiv.className = 'flex items-center justify-between bg-gray-700 p-3 rounded-lg text-sm'; + + const infoContainer = document.createElement('div'); + infoContainer.className = 'flex flex-col overflow-hidden'; + + const nameSpan = document.createElement('div'); + nameSpan.className = 'truncate font-medium text-gray-200 text-sm mb-1'; + nameSpan.textContent = file.name; + + const metaSpan = document.createElement('div'); + metaSpan.className = 'text-xs text-gray-400'; + metaSpan.textContent = formatBytes(file.size); + + infoContainer.append(nameSpan, metaSpan); + + const removeBtn = document.createElement('button'); + removeBtn.className = 'ml-4 text-red-400 hover:text-red-300 flex-shrink-0'; + removeBtn.innerHTML = ''; + removeBtn.onclick = () => { + state.files = state.files.filter((_, i) => i !== index); + updateUI(); + }; + + fileDiv.append(infoContainer, removeBtn); + fileDisplayArea.appendChild(fileDiv); + } + + createIcons({ icons }); + fileControls.classList.remove('hidden'); + processBtn.classList.remove('hidden'); + (processBtn as HTMLButtonElement).disabled = false; + } else { + fileDisplayArea.innerHTML = ''; + fileControls.classList.add('hidden'); + processBtn.classList.add('hidden'); + (processBtn as HTMLButtonElement).disabled = true; + } + }; + + const resetState = () => { + state.files = []; + state.pdfDoc = null; + updateUI(); + }; + + const convertToPdf = async () => { + try { + if (state.files.length === 0) { + showAlert('No Files', `Please select at least one ${TOOL_NAME} file.`); + return; + } + + showLoader('Loading engine...'); + const pymupdf = new PyMuPDF(getWasmBaseUrl('pymupdf')); + await pymupdf.load(); + + if (state.files.length === 1) { + const originalFile = state.files[0]; + showLoader(`Converting ${originalFile.name}...`); + + const pdfBlob = await pymupdf.convertToPdf(originalFile, { filetype: FILETYPE }); + const fileName = originalFile.name.replace(/\.[^.]+$/, '') + '.pdf'; + + downloadFile(pdfBlob, fileName); + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${originalFile.name} to PDF.`, + 'success', + () => resetState() + ); + } else { + showLoader('Converting files...'); + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + for (let i = 0; i < state.files.length; i++) { + const file = state.files[i]; + showLoader(`Converting ${i + 1}/${state.files.length}: ${file.name}...`); + + const pdfBlob = await pymupdf.convertToPdf(file, { filetype: FILETYPE }); + const baseName = file.name.replace(/\.[^.]+$/, ''); + const pdfBuffer = await pdfBlob.arrayBuffer(); + zip.file(`${baseName}.pdf`, pdfBuffer); + } + + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile(zipBlob, `${FILETYPE}-converted.zip`); + + hideLoader(); + + showAlert( + 'Conversion Complete', + `Successfully converted ${state.files.length} ${TOOL_NAME} file(s) to PDF.`, + 'success', + () => resetState() + ); + } + } catch (e: any) { + console.error(`[${TOOL_NAME}2PDF] ERROR:`, e); + hideLoader(); + showAlert('Error', `An error occurred during conversion. Error: ${e.message}`); + } + }; + + const handleFileSelect = (files: FileList | null) => { + if (files && files.length > 0) { + state.files = [...state.files, ...Array.from(files)]; + updateUI(); + } + }; + + if (fileInput && dropZone) { + fileInput.addEventListener('change', (e) => { + handleFileSelect((e.target as HTMLInputElement).files); + }); + + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('bg-gray-700'); + }); + + dropZone.addEventListener('dragleave', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + }); + + dropZone.addEventListener('drop', (e) => { + e.preventDefault(); + dropZone.classList.remove('bg-gray-700'); + const files = e.dataTransfer?.files; + if (files && files.length > 0) { + const validFiles = Array.from(files).filter(f => { + const name = f.name.toLowerCase(); + return EXTENSIONS.some(ext => name.endsWith(ext)); + }); + if (validFiles.length > 0) { + const dataTransfer = new DataTransfer(); + validFiles.forEach(f => dataTransfer.items.add(f)); + handleFileSelect(dataTransfer.files); + } + } + }); + + fileInput.addEventListener('click', () => { + fileInput.value = ''; + }); + } + + if (addMoreBtn) { + addMoreBtn.addEventListener('click', () => { + fileInput.click(); + }); + } + + if (clearFilesBtn) { + clearFilesBtn.addEventListener('click', () => { + resetState(); + }); + } + + if (processBtn) { + processBtn.addEventListener('click', convertToPdf); + } +}); diff --git a/src/js/main.ts b/src/js/main.ts index 5c00592..d05df06 100644 --- a/src/js/main.ts +++ b/src/js/main.ts @@ -1,50 +1,41 @@ import { categories } from './config/tools.js'; -import { dom, switchView, hideAlert, showLoader, hideLoader, showAlert } from './ui.js'; -import { state, resetState } from './state.js'; +import { dom, switchView, hideAlert } from './ui.js'; import { ShortcutsManager } from './logic/shortcuts.js'; import { createIcons, icons } from 'lucide'; +import '@phosphor-icons/web/regular'; import * as pdfjsLib from 'pdfjs-dist'; import '../css/styles.css'; import { formatShortcutDisplay, formatStars } from './utils/helpers.js'; -import { APP_VERSION, injectVersion } from '../version.js'; -import { initI18n, applyTranslations, rewriteLinks, injectLanguageSwitcher, createLanguageSwitcher, t } from './i18n/index.js'; +import { APP_VERSION } from '../version.js'; +import { + initI18n, + applyTranslations, + rewriteLinks, + injectLanguageSwitcher, + createLanguageSwitcher, + t, +} from './i18n/index.js'; +import { startBackgroundPreload } from './utils/wasm-preloader.js'; const init = async () => { await initI18n(); injectLanguageSwitcher(); applyTranslations(); - pdfjsLib.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString(); + pdfjsLib.GlobalWorkerOptions.workerSrc = new URL( + 'pdfjs-dist/build/pdf.worker.min.mjs', + import.meta.url + ).toString(); if (__SIMPLE_MODE__) { const hideBrandingSections = () => { - const nav = document.querySelector('nav'); - if (nav) { - nav.style.display = 'none'; - - const simpleNav = document.createElement('nav'); - simpleNav.className = - 'bg-gray-800 border-b border-gray-700 sticky top-0 z-30'; - simpleNav.innerHTML = ` -
-
- -
-
- `; - document.body.insertBefore(simpleNav, document.body.firstChild); - } - const heroSection = document.getElementById('hero-section'); if (heroSection) { heroSection.style.display = 'none'; } - const githubLink = document.querySelector('a[href*="github.com/alam00000/bentopdf"]'); + const githubLink = document.querySelector( + 'a[href*="github.com/alam00000/bentopdf"]' + ); if (githubLink) { (githubLink as HTMLElement).style.display = 'none'; } @@ -79,51 +70,13 @@ const init = async () => { } // Hide "Used by companies" section - const usedBySection = document.querySelector('.hide-section') as HTMLElement; + const usedBySection = document.querySelector( + '.hide-section' + ) as HTMLElement; if (usedBySection) { usedBySection.style.display = 'none'; } - const footer = document.querySelector('footer'); - if (footer && !document.querySelector('[data-simple-footer]')) { - footer.style.display = 'none'; - - const simpleFooter = document.createElement('footer'); - simpleFooter.className = 'mt-16 border-t-2 border-gray-700 py-8'; - simpleFooter.setAttribute('data-simple-footer', 'true'); - simpleFooter.innerHTML = ` -
-
-
-
- Bento PDF Logo - BentoPDF -
-

- © 2025 BentoPDF. All rights reserved. -

-

- Version ${APP_VERSION} -

-
-
-
-
- `; - document.body.appendChild(simpleFooter); - - const langContainer = simpleFooter.querySelector('#simple-mode-lang-switcher'); - if (langContainer) { - const switcher = createLanguageSwitcher(); - const dropdown = switcher.querySelector('div[role="menu"]'); - if (dropdown) { - dropdown.classList.remove('mt-2'); - dropdown.classList.add('bottom-full', 'mb-2'); - } - langContainer.appendChild(switcher); - } - } - const sectionDividers = document.querySelectorAll('.section-divider'); sectionDividers.forEach((divider) => { (divider as HTMLElement).style.display = 'none'; @@ -165,13 +118,14 @@ const init = async () => { if (shortcutSettingsBtn) shortcutSettingsBtn.style.display = 'none'; } else { if (keyboardShortcutBtn) { - keyboardShortcutBtn.textContent = navigator.userAgent.toUpperCase().includes('MAC') + keyboardShortcutBtn.textContent = navigator.userAgent + .toUpperCase() + .includes('MAC') ? '⌘ + K' : 'Ctrl + K'; } } - const categoryTranslationKeys: Record = { 'Popular Tools': 'tools:categories.popularTools', 'Edit & Annotate': 'tools:categories.editAnnotate', @@ -207,7 +161,7 @@ const init = async () => { 'PDF Form Filler': 'tools:pdfFormFiller', 'Create PDF Form': 'tools:createPdfForm', 'Remove Blank Pages': 'tools:removeBlankPages', - 'Image to PDF': 'tools:imageToPdf', + 'Images to PDF': 'tools:imageToPdf', 'PNG to PDF': 'tools:pngToPdf', 'WebP to PDF': 'tools:webpToPdf', 'SVG to PDF': 'tools:svgToPdf', @@ -233,6 +187,7 @@ const init = async () => { 'Add Blank Page': 'tools:addBlankPage', 'Reverse Pages': 'tools:reversePages', 'Rotate PDF': 'tools:rotatePdf', + 'Rotate by Custom Degrees': 'tools:rotateCustom', 'N-Up PDF': 'tools:nUpPdf', 'Combine to Single Page': 'tools:combineToSinglePage', 'View Metadata': 'tools:viewMetadata', @@ -251,6 +206,11 @@ const init = async () => { 'Flatten PDF': 'tools:flattenPdf', 'Remove Metadata': 'tools:removeMetadata', 'Change Permissions': 'tools:changePermissions', + 'Email to PDF': 'tools:emailToPdf', + 'Font to Outline': 'tools:fontToOutline', + 'Deskew PDF': 'tools:deskewPdf', + 'Digital Signature': 'tools:digitalSignPdf', + 'Validate Signature': 'tools:validateSignaturePdf', }; // Homepage-only tool grid rendering (not used on individual tool pages) @@ -262,7 +222,8 @@ const init = async () => { categoryGroup.className = 'category-group col-span-full'; const title = document.createElement('h2'); - title.className = 'text-xl font-bold text-indigo-400 mb-4 mt-8 first:mt-0 text-white'; + title.className = + 'text-xl font-bold text-indigo-400 mb-4 mt-8 first:mt-0 text-white'; const categoryKey = categoryTranslationKeys[category.name]; title.textContent = categoryKey ? t(categoryKey) : category.name; @@ -287,7 +248,12 @@ const init = async () => { const icon = document.createElement('i'); icon.className = 'w-10 h-10 mb-3 text-indigo-400'; - icon.setAttribute('data-lucide', tool.icon); + + if (tool.icon.startsWith('ph-')) { + icon.className = `ph ${tool.icon} text-4xl mb-3 text-indigo-400`; + } else { + icon.setAttribute('data-lucide', tool.icon); + } const toolName = document.createElement('h3'); toolName.className = 'font-semibold text-white'; @@ -299,7 +265,9 @@ const init = async () => { if (tool.subtitle) { const toolSubtitle = document.createElement('p'); toolSubtitle.className = 'text-xs text-gray-400 mt-1 px-2'; - toolSubtitle.textContent = toolKey ? t(`${toolKey}.subtitle`) : tool.subtitle; + toolSubtitle.textContent = toolKey + ? t(`${toolKey}.subtitle`) + : tool.subtitle; toolCard.appendChild(toolSubtitle); } @@ -313,46 +281,73 @@ const init = async () => { const searchBar = document.getElementById('search-bar'); const categoryGroups = dom.toolGrid.querySelectorAll('.category-group'); - const fuzzyMatch = (searchTerm: string, targetText: string): boolean => { - if (!searchTerm) return true; - - let searchIndex = 0; - let targetIndex = 0; - - while (searchIndex < searchTerm.length && targetIndex < targetText.length) { - if (searchTerm[searchIndex] === targetText[targetIndex]) { - searchIndex++; - } - targetIndex++; - } - - return searchIndex === searchTerm.length; - }; + const searchResultsContainer = document.createElement('div'); + searchResultsContainer.id = 'search-results'; + searchResultsContainer.className = + 'hidden grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4 md:gap-6 col-span-full'; + dom.toolGrid.insertBefore(searchResultsContainer, dom.toolGrid.firstChild); searchBar.addEventListener('input', () => { // @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'HTMLEleme... Remove this comment to see the full error message const searchTerm = searchBar.value.toLowerCase().trim(); + if (!searchTerm) { + searchResultsContainer.classList.add('hidden'); + searchResultsContainer.innerHTML = ''; + categoryGroups.forEach((group) => { + (group as HTMLElement).style.display = ''; + const toolCards = group.querySelectorAll('.tool-card'); + toolCards.forEach((card) => { + (card as HTMLElement).style.display = ''; + }); + }); + return; + } + categoryGroups.forEach((group) => { - const toolCards = group.querySelectorAll('.tool-card'); - let visibleToolsInCategory = 0; + (group as HTMLElement).style.display = 'none'; + }); + + searchResultsContainer.innerHTML = ''; + searchResultsContainer.classList.remove('hidden'); + + const seenToolIds = new Set(); + const allTools: HTMLElement[] = []; + + categoryGroups.forEach((group) => { + const toolCards = Array.from(group.querySelectorAll('.tool-card')); toolCards.forEach((card) => { - const toolName = card.querySelector('h3').textContent.toLowerCase(); - const toolSubtitle = - card.querySelector('p')?.textContent.toLowerCase() || ''; + const toolName = ( + card.querySelector('h3')?.textContent || '' + ).toLowerCase(); + const toolSubtitle = ( + card.querySelector('p')?.textContent || '' + ).toLowerCase(); + const toolHref = + (card as HTMLAnchorElement).href || + (card as HTMLElement).dataset.toolId || + ''; + + const toolId = + toolHref.split('/').pop()?.replace('.html', '') || toolName; const isMatch = - fuzzyMatch(searchTerm, toolName) || fuzzyMatch(searchTerm, toolSubtitle); + toolName.includes(searchTerm) || toolSubtitle.includes(searchTerm); + const isDuplicate = seenToolIds.has(toolId); - card.classList.toggle('hidden', !isMatch); - if (isMatch) { - visibleToolsInCategory++; + if (isMatch && !isDuplicate) { + seenToolIds.add(toolId); + allTools.push(card.cloneNode(true) as HTMLElement); } }); - - group.classList.toggle('hidden', visibleToolsInCategory === 0); }); + + allTools.forEach((tool) => { + searchResultsContainer.appendChild(tool); + }); + + createIcons({ icons }); }); window.addEventListener('keydown', function (e) { @@ -403,31 +398,32 @@ const init = async () => { createIcons({ icons }); console.log('Please share our tool and share the love!'); + // Start background WASM preloading on all pages + startBackgroundPreload(); const githubStarsElements = [ document.getElementById('github-stars-desktop'), - document.getElementById('github-stars-mobile') + document.getElementById('github-stars-mobile'), ]; - if (githubStarsElements.some(el => el) && !__SIMPLE_MODE__) { + if (githubStarsElements.some((el) => el) && !__SIMPLE_MODE__) { fetch('https://api.github.com/repos/alam00000/bentopdf') .then((response) => response.json()) .then((data) => { if (data.stargazers_count !== undefined) { const formattedStars = formatStars(data.stargazers_count); - githubStarsElements.forEach(el => { + githubStarsElements.forEach((el) => { if (el) el.textContent = formattedStars; }); } }) .catch(() => { - githubStarsElements.forEach(el => { + githubStarsElements.forEach((el) => { if (el) el.textContent = '-'; }); }); } - // Initialize Shortcuts System ShortcutsManager.init(); @@ -435,9 +431,13 @@ const init = async () => { const shortcutsTabBtn = document.getElementById('shortcuts-tab-btn'); const preferencesTabBtn = document.getElementById('preferences-tab-btn'); const shortcutsTabContent = document.getElementById('shortcuts-tab-content'); - const preferencesTabContent = document.getElementById('preferences-tab-content'); + const preferencesTabContent = document.getElementById( + 'preferences-tab-content' + ); const shortcutsTabFooter = document.getElementById('shortcuts-tab-footer'); - const preferencesTabFooter = document.getElementById('preferences-tab-footer'); + const preferencesTabFooter = document.getElementById( + 'preferences-tab-footer' + ); const resetShortcutsBtn = document.getElementById('reset-shortcuts-btn'); if (shortcutsTabBtn && preferencesTabBtn) { @@ -467,11 +467,12 @@ const init = async () => { } // Full-width toggle functionality - const fullWidthToggle = document.getElementById('full-width-toggle') as HTMLInputElement; + const fullWidthToggle = document.getElementById( + 'full-width-toggle' + ) as HTMLInputElement; const toolInterface = document.getElementById('tool-interface'); - // Load saved preference - const savedFullWidth = localStorage.getItem('fullWidthMode') === 'true'; + const savedFullWidth = localStorage.getItem('fullWidthMode') !== 'false'; if (fullWidthToggle) { fullWidthToggle.checked = savedFullWidth; applyFullWidthMode(savedFullWidth); @@ -493,7 +494,10 @@ const init = async () => { uploader.classList.remove('max-w-2xl', 'max-w-5xl'); } else { // Restore original max-width (most are max-w-2xl, add-stamps is max-w-5xl) - if (!uploader.classList.contains('max-w-2xl') && !uploader.classList.contains('max-w-5xl')) { + if ( + !uploader.classList.contains('max-w-2xl') && + !uploader.classList.contains('max-w-5xl') + ) { uploader.classList.add('max-w-2xl'); } } @@ -614,26 +618,36 @@ const init = async () => { } // Reserved shortcuts that commonly conflict with browser/OS functions - const RESERVED_SHORTCUTS: Record = { - 'mod+w': { mac: 'Closes tab', windows: 'Closes tab' }, - 'mod+t': { mac: 'Opens new tab', windows: 'Opens new tab' }, - 'mod+n': { mac: 'Opens new window', windows: 'Opens new window' }, - 'mod+shift+n': { mac: 'Opens incognito window', windows: 'Opens incognito window' }, - 'mod+q': { mac: 'Quits application (cannot be overridden)' }, - 'mod+m': { mac: 'Minimizes window' }, - 'mod+h': { mac: 'Hides window' }, - 'mod+r': { mac: 'Reloads page', windows: 'Reloads page' }, - 'mod+shift+r': { mac: 'Hard reloads page', windows: 'Hard reloads page' }, - 'mod+l': { mac: 'Focuses address bar', windows: 'Focuses address bar' }, - 'mod+d': { mac: 'Bookmarks page', windows: 'Bookmarks page' }, - 'mod+shift+t': { mac: 'Reopens closed tab', windows: 'Reopens closed tab' }, - 'mod+shift+w': { mac: 'Closes window', windows: 'Closes window' }, - 'mod+tab': { mac: 'Switches tabs', windows: 'Switches apps' }, - 'alt+f4': { windows: 'Closes window' }, - 'ctrl+tab': { mac: 'Switches tabs', windows: 'Switches tabs' }, - }; + const RESERVED_SHORTCUTS: Record = + { + 'mod+w': { mac: 'Closes tab', windows: 'Closes tab' }, + 'mod+t': { mac: 'Opens new tab', windows: 'Opens new tab' }, + 'mod+n': { mac: 'Opens new window', windows: 'Opens new window' }, + 'mod+shift+n': { + mac: 'Opens incognito window', + windows: 'Opens incognito window', + }, + 'mod+q': { mac: 'Quits application (cannot be overridden)' }, + 'mod+m': { mac: 'Minimizes window' }, + 'mod+h': { mac: 'Hides window' }, + 'mod+r': { mac: 'Reloads page', windows: 'Reloads page' }, + 'mod+shift+r': { mac: 'Hard reloads page', windows: 'Hard reloads page' }, + 'mod+l': { mac: 'Focuses address bar', windows: 'Focuses address bar' }, + 'mod+d': { mac: 'Bookmarks page', windows: 'Bookmarks page' }, + 'mod+shift+t': { + mac: 'Reopens closed tab', + windows: 'Reopens closed tab', + }, + 'mod+shift+w': { mac: 'Closes window', windows: 'Closes window' }, + 'mod+tab': { mac: 'Switches tabs', windows: 'Switches apps' }, + 'alt+f4': { windows: 'Closes window' }, + 'ctrl+tab': { mac: 'Switches tabs', windows: 'Switches tabs' }, + }; - function getReservedShortcutWarning(combo: string, isMac: boolean): string | null { + function getReservedShortcutWarning( + combo: string, + isMac: boolean + ): string | null { const reserved = RESERVED_SHORTCUTS[combo]; if (!reserved) return null; @@ -643,9 +657,19 @@ const init = async () => { return description; } - function showWarningModal(title: string, message: string, confirmMode: boolean = true): Promise { + function showWarningModal( + title: string, + message: string, + confirmMode: boolean = true + ): Promise { return new Promise((resolve) => { - if (!dom.warningModal || !dom.warningTitle || !dom.warningMessage || !dom.warningCancelBtn || !dom.warningConfirmBtn) { + if ( + !dom.warningModal || + !dom.warningTitle || + !dom.warningMessage || + !dom.warningCancelBtn || + !dom.warningConfirmBtn + ) { resolve(confirmMode ? confirm(message) : (alert(message), true)); return; } @@ -684,15 +708,19 @@ const init = async () => { dom.warningCancelBtn.addEventListener('click', handleCancel); // Close on backdrop click - dom.warningModal.addEventListener('click', (e) => { - if (e.target === dom.warningModal) { - if (confirmMode) { - handleCancel(); - } else { - handleConfirm(); + dom.warningModal.addEventListener( + 'click', + (e) => { + if (e.target === dom.warningModal) { + if (confirmMode) { + handleCancel(); + } else { + handleConfirm(); + } } - } - }, { once: true }); + }, + { once: true } + ); }); } @@ -711,14 +739,15 @@ const init = async () => { const allShortcuts = ShortcutsManager.getAllShortcuts(); const isMac = navigator.userAgent.toUpperCase().includes('MAC'); - const allTools = categories.flatMap(c => c.tools); + const allTools = categories.flatMap((c) => c.tools); - categories.forEach(category => { + categories.forEach((category) => { const section = document.createElement('div'); section.className = 'category-section mb-6 last:mb-0'; const header = document.createElement('h3'); - header.className = 'text-gray-400 text-xs font-bold uppercase tracking-wider mb-3 pl-1'; + header.className = + 'text-gray-400 text-xs font-bold uppercase tracking-wider mb-3 pl-1'; // Translate category name const categoryKey = categoryTranslationKeys[category.name]; header.textContent = categoryKey ? t(categoryKey) : category.name; @@ -730,13 +759,14 @@ const init = async () => { let hasTools = false; - category.tools.forEach(tool => { + category.tools.forEach((tool) => { hasTools = true; const toolId = getToolId(tool); const currentShortcut = allShortcuts.get(toolId) || ''; const item = document.createElement('div'); - item.className = 'shortcut-item flex items-center justify-between p-3 bg-gray-900 rounded-lg border border-gray-700 hover:border-gray-600 transition-colors'; + item.className = + 'shortcut-item flex items-center justify-between p-3 bg-gray-900 rounded-lg border border-gray-700 hover:border-gray-600 transition-colors'; const left = document.createElement('div'); left.className = 'flex items-center gap-3'; @@ -757,13 +787,15 @@ const init = async () => { const input = document.createElement('input'); input.type = 'text'; - input.className = 'shortcut-input w-32 bg-gray-800 border border-gray-600 text-white text-center text-sm rounded px-2 py-1 focus:ring-2 focus:ring-indigo-500 focus:border-transparent outline-none transition-all'; + input.className = + 'shortcut-input w-32 bg-gray-800 border border-gray-600 text-white text-center text-sm rounded px-2 py-1 focus:ring-2 focus:ring-indigo-500 focus:border-transparent outline-none transition-all'; input.placeholder = t('settings.clickToSet'); input.value = formatShortcutDisplay(currentShortcut, isMac); input.readOnly = true; const clearBtn = document.createElement('button'); - clearBtn.className = 'absolute -right-2 -top-2 bg-gray-700 hover:bg-red-600 text-white rounded-full p-0.5 hidden group-hover:block shadow-sm'; + clearBtn.className = + 'absolute -right-2 -top-2 bg-gray-700 hover:bg-red-600 text-white rounded-full p-0.5 hidden group-hover:block shadow-sm'; clearBtn.innerHTML = ''; if (currentShortcut) { right.classList.add('group'); @@ -812,7 +844,10 @@ const init = async () => { // Ignore dead keys (used for accented characters on Mac with Option key) if (isDeadKey) { - input.value = formatShortcutDisplay(ShortcutsManager.getShortcut(toolId) || '', isMac); + input.value = formatShortcutDisplay( + ShortcutsManager.getShortcut(toolId) || '', + isMac + ); return; } @@ -828,22 +863,31 @@ const init = async () => { const existingToolId = ShortcutsManager.findToolByShortcut(combo); if (existingToolId && existingToolId !== toolId) { - const existingTool = allTools.find(t => getToolId(t) === existingToolId); + const existingTool = allTools.find( + (t) => getToolId(t) === existingToolId + ); const existingToolName = existingTool?.name || existingToolId; const displayCombo = formatShortcutDisplay(combo, isMac); - const existingToolKey = existingTool ? toolTranslationKeys[existingTool.name] : null; - const translatedToolName = existingToolKey ? t(`${existingToolKey}.name`) : existingToolName; + const existingToolKey = existingTool + ? toolTranslationKeys[existingTool.name] + : null; + const translatedToolName = existingToolKey + ? t(`${existingToolKey}.name`) + : existingToolName; await showWarningModal( t('settings.warnings.alreadyInUse'), `${displayCombo} ${t('settings.warnings.assignedTo')}

` + - `"${translatedToolName}"

` + - t('settings.warnings.chooseDifferent'), + `"${translatedToolName}"

` + + t('settings.warnings.chooseDifferent'), false ); - input.value = formatShortcutDisplay(ShortcutsManager.getShortcut(toolId) || '', isMac); + input.value = formatShortcutDisplay( + ShortcutsManager.getShortcut(toolId) || '', + isMac + ); input.classList.remove('border-indigo-500', 'text-indigo-400'); input.blur(); return; @@ -855,14 +899,17 @@ const init = async () => { const shouldProceed = await showWarningModal( t('settings.warnings.reserved'), `${displayCombo} ${t('settings.warnings.commonlyUsed')}

` + - `"${reservedWarning}"

` + - `${t('settings.warnings.unreliable')}

` + - t('settings.warnings.useAnyway') + `"${reservedWarning}"

` + + `${t('settings.warnings.unreliable')}

` + + t('settings.warnings.useAnyway') ); if (!shouldProceed) { // Revert display - input.value = formatShortcutDisplay(ShortcutsManager.getShortcut(toolId) || '', isMac); + input.value = formatShortcutDisplay( + ShortcutsManager.getShortcut(toolId) || '', + isMac + ); input.classList.remove('border-indigo-500', 'text-indigo-400'); input.blur(); return; @@ -889,7 +936,10 @@ const init = async () => { }; input.onblur = () => { - input.value = formatShortcutDisplay(ShortcutsManager.getShortcut(toolId) || '', isMac); + input.value = formatShortcutDisplay( + ShortcutsManager.getShortcut(toolId) || '', + isMac + ); input.classList.remove('border-indigo-500', 'text-indigo-400'); }; @@ -928,7 +978,7 @@ const init = async () => { scrollToTopBtn.addEventListener('click', () => { window.scrollTo({ top: 0, - behavior: 'instant' + behavior: 'instant', }); }); } diff --git a/src/js/sw-register.ts b/src/js/sw-register.ts new file mode 100644 index 0000000..1c21b7a --- /dev/null +++ b/src/js/sw-register.ts @@ -0,0 +1,55 @@ +/** + * Service Worker Registration + * Registers the service worker to enable offline caching + * + * Note: Service Worker is disabled in development mode to prevent + * conflicts with Vite's HMR (Hot Module Replacement) + */ + +// Skip service worker registration in development mode +const isDevelopment = window.location.hostname === 'localhost' || + window.location.hostname === '127.0.0.1' || + window.location.port !== ''; + +if (isDevelopment) { + console.log('[Dev Mode] Service Worker registration skipped in development'); + console.log('Service Worker will be active in production builds'); +} else if ('serviceWorker' in navigator) { + window.addEventListener('load', () => { + const swPath = `${import.meta.env.BASE_URL}sw.js`; + console.log('[SW] Registering Service Worker at:', swPath); + navigator.serviceWorker + .register(swPath) + .then((registration) => { + console.log('[SW] Service Worker registered successfully:', registration.scope); + + setInterval(() => { + registration.update(); + }, 24 * 60 * 60 * 1000); + + registration.addEventListener('updatefound', () => { + const newWorker = registration.installing; + if (newWorker) { + newWorker.addEventListener('statechange', () => { + if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { + console.log('[SW] New version available! Reload to update.'); + + if (confirm('A new version of BentoPDF is available. Reload to update?')) { + newWorker.postMessage({ type: 'SKIP_WAITING' }); + window.location.reload(); + } + } + }); + } + }); + }) + .catch((error) => { + console.error('[SW] Service Worker registration failed:', error); + }); + + navigator.serviceWorker.addEventListener('controllerchange', () => { + console.log('[SW] New service worker activated, reloading...'); + window.location.reload(); + }); + }); +} diff --git a/src/js/types/add-blank-page-type.ts b/src/js/types/add-blank-page-type.ts new file mode 100644 index 0000000..3d2f03c --- /dev/null +++ b/src/js/types/add-blank-page-type.ts @@ -0,0 +1,6 @@ +import { PDFDocument as PDFLibDocument } from 'pdf-lib'; + +export interface AddBlankPageState { + file: File | null; + pdfDoc: PDFLibDocument | null; +} \ No newline at end of file diff --git a/src/js/types/add-watermark-type.ts b/src/js/types/add-watermark-type.ts new file mode 100644 index 0000000..583d112 --- /dev/null +++ b/src/js/types/add-watermark-type.ts @@ -0,0 +1,6 @@ +import { PDFDocument as PDFLibDocument } from 'pdf-lib'; + +export interface AddWatermarkState { + file: File | null; + pdfDoc: PDFLibDocument | null; +} \ No newline at end of file diff --git a/src/js/types/alternate-merge-page-type.ts b/src/js/types/alternate-merge-page-type.ts new file mode 100644 index 0000000..488ecb7 --- /dev/null +++ b/src/js/types/alternate-merge-page-type.ts @@ -0,0 +1,5 @@ +export interface AlternateMergeState { + files: File[]; + pdfBytes: Map; + pdfDocs: Map; +} \ No newline at end of file diff --git a/src/js/types/attachment-type.ts b/src/js/types/attachment-type.ts new file mode 100644 index 0000000..a2cc85a --- /dev/null +++ b/src/js/types/attachment-type.ts @@ -0,0 +1,7 @@ +import { PDFDocument as PDFLibDocument } from 'pdf-lib'; + +export interface AddAttachmentState { + file: File | null; + pdfDoc: PDFLibDocument | null; + attachments: File[]; +} \ No newline at end of file diff --git a/src/js/types/background-color-type.ts b/src/js/types/background-color-type.ts new file mode 100644 index 0000000..9235ba8 --- /dev/null +++ b/src/js/types/background-color-type.ts @@ -0,0 +1,6 @@ +import { PDFDocument as PDFLibDocument } from 'pdf-lib'; + +export interface BackgroundColorState { + file: File | null; + pdfDoc: PDFLibDocument | null; +} diff --git a/src/js/types/bookmark-pdf-type.ts b/src/js/types/bookmark-pdf-type.ts new file mode 100644 index 0000000..805beb5 --- /dev/null +++ b/src/js/types/bookmark-pdf-type.ts @@ -0,0 +1,179 @@ +import { PDFDocument as PDFLibDocument, PDFRef } from 'pdf-lib'; +import { PDFDocumentProxy, PageViewport } from 'pdfjs-dist'; + +// Core bookmark types +export type BookmarkColor = + | 'red' + | 'blue' + | 'green' + | 'yellow' + | 'purple' + | null; +export type BookmarkStyle = 'bold' | 'italic' | 'bold-italic' | null; + +export interface BookmarkNode { + id: number; + title: string; + page: number; + children: BookmarkNode[]; + color: BookmarkColor | string; + style: BookmarkStyle; + destX: number | null; + destY: number | null; + zoom: string | null; +} + +export type BookmarkTree = BookmarkNode[]; + +// Modal system types +export type ModalFieldType = 'text' | 'select' | 'destination' | 'preview'; + +export interface SelectOption { + value: string; + label: string; +} + +export interface BaseModalField { + name: string; + label: string; +} + +export interface TextModalField extends BaseModalField { + type: 'text'; + placeholder?: string; +} + +export interface SelectModalField extends BaseModalField { + type: 'select'; + options: SelectOption[]; +} + +export interface DestinationModalField extends BaseModalField { + type: 'destination'; + page?: number; + maxPages?: number; +} + +export interface PreviewModalField { + type: 'preview'; + label: string; +} + +export type ModalField = + | TextModalField + | SelectModalField + | DestinationModalField + | PreviewModalField; + +export interface ModalResult { + title?: string; + color?: string; + style?: string; + destPage?: number | null; + destX?: number | null; + destY?: number | null; + zoom?: string | null; + [key: string]: string | number | null | undefined; +} + +export interface ModalDefaultValues { + title?: string; + color?: string; + style?: string; + destPage?: number; + destX?: number | null; + destY?: number | null; + zoom?: string | null; + [key: string]: string | number | null | undefined; +} + +// Destination picking types +export type DestinationCallback = ( + page: number, + pdfX: number, + pdfY: number +) => void; + +export interface DestinationPickingState { + isPickingDestination: boolean; + currentPickingCallback: DestinationCallback | null; + destinationMarker: HTMLDivElement | null; + savedModalOverlay: HTMLDivElement | null; + savedModal: HTMLDivElement | null; + currentViewport: PageViewport | null; +} + +// State types +export interface BookmarkEditorState { + pdfLibDoc: PDFLibDocument | null; + pdfJsDoc: PDFDocumentProxy | null; + currentPage: number; + currentZoom: number; + originalFileName: string; + bookmarkTree: BookmarkTree; + history: BookmarkTree[]; + historyIndex: number; + searchQuery: string; + csvBookmarks: BookmarkTree | null; + jsonBookmarks: BookmarkTree | null; + batchMode: boolean; + selectedBookmarks: Set; + collapsedNodes: Set; +} + +// PDF outline types (from pdfjs-dist) +export interface PDFOutlineItem { + title: string; + dest: string | unknown[] | null; + items?: PDFOutlineItem[]; + color?: Uint8ClampedArray | [number, number, number]; + bold?: boolean; + italic?: boolean; +} + +export interface FlattenedBookmark extends BookmarkNode { + level: number; +} + +// Outline item for PDF creation +export interface OutlineItem { + ref: PDFRef; + dict: { + set: (key: unknown, value: unknown) => void; + }; +} + +// Color mapping types +export type ColorClassMap = Record; + +export const COLOR_CLASSES: ColorClassMap = { + red: 'bg-red-100 border-red-300', + blue: 'bg-blue-100 border-blue-300', + green: 'bg-green-100 border-green-300', + yellow: 'bg-yellow-100 border-yellow-300', + purple: 'bg-purple-100 border-purple-300', +}; + +export const TEXT_COLOR_CLASSES: ColorClassMap = { + red: 'text-red-600', + blue: 'text-blue-600', + green: 'text-green-600', + yellow: 'text-yellow-600', + purple: 'text-purple-600', +}; + +export const HEX_COLOR_MAP: Record = { + red: '#dc2626', + blue: '#2563eb', + green: '#16a34a', + yellow: '#ca8a04', + purple: '#9333ea', +}; + +export const PDF_COLOR_MAP: Record = { + red: [1.0, 0.0, 0.0], + blue: [0.0, 0.0, 1.0], + green: [0.0, 1.0, 0.0], + yellow: [1.0, 1.0, 0.0], + purple: [0.5, 0.0, 0.5], +}; diff --git a/src/js/types/change-permissions-type.ts b/src/js/types/change-permissions-type.ts new file mode 100644 index 0000000..5c1a954 --- /dev/null +++ b/src/js/types/change-permissions-type.ts @@ -0,0 +1,3 @@ +export interface ChangePermissionsState { + file: File | null; +} diff --git a/src/js/types/combine-single-page-type.ts b/src/js/types/combine-single-page-type.ts new file mode 100644 index 0000000..7ea4389 --- /dev/null +++ b/src/js/types/combine-single-page-type.ts @@ -0,0 +1,6 @@ +import { PDFDocument as PDFLibDocument } from 'pdf-lib'; + +export interface CombineSinglePageState { + file: File | null; + pdfDoc: PDFLibDocument | null; +} diff --git a/src/js/types/compare-pdfs-type.ts b/src/js/types/compare-pdfs-type.ts new file mode 100644 index 0000000..de54566 --- /dev/null +++ b/src/js/types/compare-pdfs-type.ts @@ -0,0 +1,9 @@ +import * as pdfjsLib from 'pdfjs-dist'; + +export interface CompareState { + pdfDoc1: pdfjsLib.PDFDocumentProxy | null; + pdfDoc2: pdfjsLib.PDFDocumentProxy | null; + currentPage: number; + viewMode: 'overlay' | 'side-by-side'; + isSyncScroll: boolean; +} diff --git a/src/js/types/crop-pdf-type.ts b/src/js/types/crop-pdf-type.ts new file mode 100644 index 0000000..7b8bcf6 --- /dev/null +++ b/src/js/types/crop-pdf-type.ts @@ -0,0 +1,8 @@ +export interface CropperState { + pdfDoc: any; + currentPageNum: number; + cropper: any; + originalPdfBytes: ArrayBuffer | null; + pageCrops: Record; + file: File | null; +} diff --git a/src/js/types/decrypt-pdf-type.ts b/src/js/types/decrypt-pdf-type.ts new file mode 100644 index 0000000..15ec438 --- /dev/null +++ b/src/js/types/decrypt-pdf-type.ts @@ -0,0 +1,3 @@ +export interface DecryptPdfState { + file: File | null; +} diff --git a/src/js/types/delete-pages-type.ts b/src/js/types/delete-pages-type.ts new file mode 100644 index 0000000..0f42730 --- /dev/null +++ b/src/js/types/delete-pages-type.ts @@ -0,0 +1,7 @@ +export interface DeletePagesState { + file: File | null; + pdfDoc: any; + pdfJsDoc: any; + totalPages: number; + pagesToDelete: Set; +} diff --git a/src/js/types/digital-sign-type.ts b/src/js/types/digital-sign-type.ts new file mode 100644 index 0000000..84c648e --- /dev/null +++ b/src/js/types/digital-sign-type.ts @@ -0,0 +1,42 @@ +import { forge } from "zgapdfsigner"; + +export interface SignatureInfo { + reason?: string; + location?: string; + contactInfo?: string; + name?: string; +} + +export interface CertificateData { + p12Buffer: ArrayBuffer; + password: string; + certificate: forge.pki.Certificate; +} + +export interface SignPdfOptions { + signatureInfo?: SignatureInfo; + visibleSignature?: VisibleSignatureOptions; +} + +export interface VisibleSignatureOptions { + enabled: boolean; + imageData?: ArrayBuffer; + imageType?: 'png' | 'jpeg' | 'webp'; + x: number; + y: number; + width: number; + height: number; + page: number | string; + text?: string; + textColor?: string; + textSize?: number; +} + +export interface DigitalSignState { + pdfFile: File | null; + pdfBytes: Uint8Array | null; + certFile: File | null; + certData: CertificateData | null; + sigImageData: ArrayBuffer | null; + sigImageType: 'png' | 'jpeg' | 'webp' | null; +} \ No newline at end of file diff --git a/src/js/types/divide-pages-type.ts b/src/js/types/divide-pages-type.ts new file mode 100644 index 0000000..fc8b72a --- /dev/null +++ b/src/js/types/divide-pages-type.ts @@ -0,0 +1,7 @@ +import { PDFDocument as PDFLibDocument } from 'pdf-lib'; + +export interface DividePagesState { + file: File | null; + pdfDoc: PDFLibDocument | null; + totalPages: number; +} \ No newline at end of file diff --git a/src/js/types/edit-attachments-type.ts b/src/js/types/edit-attachments-type.ts new file mode 100644 index 0000000..0c0f438 --- /dev/null +++ b/src/js/types/edit-attachments-type.ts @@ -0,0 +1,12 @@ +export interface AttachmentInfo { + index: number; + name: string; + page: number; + data: Uint8Array; +} + +export interface EditAttachmentState { + file: File | null; + allAttachments: AttachmentInfo[]; + attachmentsToRemove: Set; +} \ No newline at end of file diff --git a/src/js/types/edit-metadata-type.ts b/src/js/types/edit-metadata-type.ts new file mode 100644 index 0000000..b62e6c4 --- /dev/null +++ b/src/js/types/edit-metadata-type.ts @@ -0,0 +1,6 @@ +import { PDFDocument as PDFLibDocument } from 'pdf-lib'; + +export interface EditMetadataState { + file: File | null; + pdfDoc: PDFLibDocument | null; +} \ No newline at end of file diff --git a/src/js/types/email-to-pdf-type.ts b/src/js/types/email-to-pdf-type.ts new file mode 100644 index 0000000..89d8166 --- /dev/null +++ b/src/js/types/email-to-pdf-type.ts @@ -0,0 +1,26 @@ +export interface EmailAttachment { + filename: string; + size: number; + contentType: string; + content?: Uint8Array; + contentId?: string; +} + +export interface ParsedEmail { + subject: string; + from: string; + to: string[]; + cc: string[]; + bcc: string[]; + date: Date | null; + rawDateString: string; + htmlBody: string; + textBody: string; + attachments: EmailAttachment[]; +} + +export interface EmailRenderOptions { + includeCcBcc?: boolean; + includeAttachments?: boolean; + pageSize?: 'a4' | 'letter' | 'legal'; +} diff --git a/src/js/types/encrypt-pdf-type.ts b/src/js/types/encrypt-pdf-type.ts new file mode 100644 index 0000000..8acd7a2 --- /dev/null +++ b/src/js/types/encrypt-pdf-type.ts @@ -0,0 +1,3 @@ +export interface EncryptPdfState { + file: File | null; +} diff --git a/src/js/types/extract-attachments-type.ts b/src/js/types/extract-attachments-type.ts new file mode 100644 index 0000000..a1cbadb --- /dev/null +++ b/src/js/types/extract-attachments-type.ts @@ -0,0 +1,3 @@ +export interface ExtractAttachmentsState { + files: File[]; +} diff --git a/src/js/types/extract-images-type.ts b/src/js/types/extract-images-type.ts new file mode 100644 index 0000000..a436909 --- /dev/null +++ b/src/js/types/extract-images-type.ts @@ -0,0 +1,7 @@ +export interface ExtractedImage { + data: Blob; + width: number; + height: number; + pageNumber: number; + imageIndex: number; +} diff --git a/src/js/types/extract-pages-type.ts b/src/js/types/extract-pages-type.ts new file mode 100644 index 0000000..9791731 --- /dev/null +++ b/src/js/types/extract-pages-type.ts @@ -0,0 +1,5 @@ +export interface ExtractPagesState { + file: File | null; + pdfBytes: ArrayBuffer | null; + totalPages: number; +} diff --git a/src/js/types/fix-page-size-type.ts b/src/js/types/fix-page-size-type.ts new file mode 100644 index 0000000..e286afd --- /dev/null +++ b/src/js/types/fix-page-size-type.ts @@ -0,0 +1,3 @@ +export interface FixPageSizeState { + file: File | null; +} diff --git a/src/js/types/flatten-pdf-type.ts b/src/js/types/flatten-pdf-type.ts new file mode 100644 index 0000000..e8815f5 --- /dev/null +++ b/src/js/types/flatten-pdf-type.ts @@ -0,0 +1,3 @@ +export interface FlattenPdfState { + files: File[]; +} diff --git a/src/js/types/form-creator.ts b/src/js/types/form-creator-type.ts similarity index 100% rename from src/js/types/form-creator.ts rename to src/js/types/form-creator-type.ts diff --git a/src/js/types/header-footer-type.ts b/src/js/types/header-footer-type.ts new file mode 100644 index 0000000..2a9d1b6 --- /dev/null +++ b/src/js/types/header-footer-type.ts @@ -0,0 +1,6 @@ +import { PDFDocument as PDFLibDocument } from 'pdf-lib'; + +export interface HeaderFooterState { + file: File | null; + pdfDoc: PDFLibDocument | null; +} diff --git a/src/js/types/index.ts b/src/js/types/index.ts index 1e88b7b..089a0ad 100644 --- a/src/js/types/index.ts +++ b/src/js/types/index.ts @@ -1,2 +1,49 @@ -export * from './ocr.js'; -export * from './form-creator.js'; +export * from './ocr-type.ts'; +export * from './form-creator-type.ts'; +export * from './digital-sign-type.ts'; +export * from './attachment-type.ts'; +export * from './edit-attachments-type.ts'; +export * from './edit-metadata-type.ts'; +export * from './divide-pages-type.ts'; +export * from './alternate-merge-page-type.ts'; +export * from './add-blank-page-type.ts'; +export * from './compare-pdfs-type.ts'; +export * from './fix-page-size-type.ts'; +export * from './view-metadata-type.ts'; +export * from './header-footer-type.ts'; +export * from './encrypt-pdf-type.ts'; +export * from './flatten-pdf-type.ts'; +export * from './crop-pdf-type.ts'; +export * from './background-color-type.ts'; +export * from './posterize-type.ts'; +export * from './decrypt-pdf-type.ts'; +export * from './combine-single-page-type.ts'; +export * from './change-permissions-type.ts'; +export * from './validate-signature-type.ts'; +export * from './remove-restrictions-type.ts'; +export * from './page-dimensions-type.ts'; +export * from './extract-attachments-type.ts'; +export * from './pdf-multi-tool-type.ts'; +export * from './ocr-pdf-type.ts'; +export * from './delete-pages-type.ts'; +export * from './invert-colors-type.ts'; +export * from './table-of-contents-type.ts'; +export * from './organize-pdf-type.ts'; +export * from './merge-pdf-type.ts'; +export * from './extract-images-type.ts'; +export * from './extract-pages-type.ts'; +export * from './pdf-layers-type.ts'; +export * from './sanitize-pdf-type.ts'; +export * from './reverse-pages-type.ts'; +export * from './text-color-type.ts'; +export * from './n-up-pdf-type.ts'; +export * from './linearize-pdf-type.ts'; +export * from './remove-metadata-type.ts'; +export * from './rotate-pdf-type.ts'; +export * from './pdf-booklet-type.ts'; +export * from './page-numbers-type.ts'; +export * from './pdf-to-zip-type.ts'; +export * from './sign-pdf-type.ts'; +export * from './add-watermark-type.ts'; +export * from './email-to-pdf-type.ts'; +export * from './bookmark-pdf-type.ts'; diff --git a/src/js/types/invert-colors-type.ts b/src/js/types/invert-colors-type.ts new file mode 100644 index 0000000..cb5abf8 --- /dev/null +++ b/src/js/types/invert-colors-type.ts @@ -0,0 +1,6 @@ +import { PDFDocument as PDFLibDocument } from 'pdf-lib'; + +export interface InvertColorsState { + file: File | null; + pdfDoc: PDFLibDocument | null; +} diff --git a/src/js/types/linearize-pdf-type.ts b/src/js/types/linearize-pdf-type.ts new file mode 100644 index 0000000..50a4c02 --- /dev/null +++ b/src/js/types/linearize-pdf-type.ts @@ -0,0 +1,3 @@ +export interface LinearizePdfState { + files: File[]; +} diff --git a/src/js/types/merge-pdf-type.ts b/src/js/types/merge-pdf-type.ts new file mode 100644 index 0000000..2fbfed9 --- /dev/null +++ b/src/js/types/merge-pdf-type.ts @@ -0,0 +1,5 @@ +export interface MergeState { + files: File[]; + pdfBytes: Map; + pdfDocs: Map; +} diff --git a/src/js/types/n-up-pdf-type.ts b/src/js/types/n-up-pdf-type.ts new file mode 100644 index 0000000..c43d1c3 --- /dev/null +++ b/src/js/types/n-up-pdf-type.ts @@ -0,0 +1,5 @@ +export interface NUpState { + file: File | null; + pdfBytes: ArrayBuffer | null; + totalPages: number; +} diff --git a/src/js/types/ocr-pdf-type.ts b/src/js/types/ocr-pdf-type.ts new file mode 100644 index 0000000..00a340d --- /dev/null +++ b/src/js/types/ocr-pdf-type.ts @@ -0,0 +1,46 @@ +export interface OcrWord { + text: string; + bbox: { x0: number; y0: number; x1: number; y1: number }; + confidence: number; +} + +export interface OcrState { + file: File | null; + searchablePdfBytes: Uint8Array | null; +} + +export interface BBox { + x0: number; // left + y0: number; // top (in hOCR coordinate system, origin at top-left) + x1: number; // right + y1: number; // bottom +} + +export interface Baseline { + slope: number; + intercept: number; +} + +export interface OcrLine { + bbox: BBox; + baseline: Baseline; + textangle: number; + words: OcrWord[]; + direction: 'ltr' | 'rtl'; + injectWordBreaks: boolean; +} + +export interface OcrPage { + width: number; + height: number; + dpi: number; + lines: OcrLine[]; +} + +export interface WordTransform { + x: number; + y: number; + fontSize: number; + horizontalScale: number; + rotation: number; +} diff --git a/src/js/types/ocr.ts b/src/js/types/ocr-type.ts similarity index 100% rename from src/js/types/ocr.ts rename to src/js/types/ocr-type.ts diff --git a/src/js/types/organize-pdf-type.ts b/src/js/types/organize-pdf-type.ts new file mode 100644 index 0000000..c12a9bf --- /dev/null +++ b/src/js/types/organize-pdf-type.ts @@ -0,0 +1,6 @@ +export interface OrganizeState { + file: File | null; + pdfBytes: ArrayBuffer | null; + totalPages: number; + pageOrder: number[]; +} diff --git a/src/js/types/page-dimensions-type.ts b/src/js/types/page-dimensions-type.ts new file mode 100644 index 0000000..9cdccd5 --- /dev/null +++ b/src/js/types/page-dimensions-type.ts @@ -0,0 +1,6 @@ +import { PDFDocument } from 'pdf-lib'; + +export interface PageDimensionsState { + file: File | null; + pdfDoc: PDFDocument | null; +} diff --git a/src/js/types/page-numbers-type.ts b/src/js/types/page-numbers-type.ts new file mode 100644 index 0000000..30fc880 --- /dev/null +++ b/src/js/types/page-numbers-type.ts @@ -0,0 +1,3 @@ +export interface PageNumbersState { + file: File | null; +} diff --git a/src/js/types/pdf-booklet-type.ts b/src/js/types/pdf-booklet-type.ts new file mode 100644 index 0000000..b2c7fcc --- /dev/null +++ b/src/js/types/pdf-booklet-type.ts @@ -0,0 +1,5 @@ +export interface BookletState { + file: File | null; + pdfBytes: ArrayBuffer | null; + totalPages: number; +} diff --git a/src/js/types/pdf-layers-type.ts b/src/js/types/pdf-layers-type.ts new file mode 100644 index 0000000..82a485d --- /dev/null +++ b/src/js/types/pdf-layers-type.ts @@ -0,0 +1,5 @@ +export interface LayerData { + name: string; + visible: boolean; + locked: boolean; +} diff --git a/src/js/types/pdf-multi-tool-type.ts b/src/js/types/pdf-multi-tool-type.ts new file mode 100644 index 0000000..69580df --- /dev/null +++ b/src/js/types/pdf-multi-tool-type.ts @@ -0,0 +1,10 @@ +export interface MultiToolPageData { + id: string; + originalPdfId: string; + pageIndex: number; + thumbnail: string; + width: number; + height: number; + rotation: number; + isBlank?: boolean; +} diff --git a/src/js/types/pdf-to-zip-type.ts b/src/js/types/pdf-to-zip-type.ts new file mode 100644 index 0000000..4c4a5de --- /dev/null +++ b/src/js/types/pdf-to-zip-type.ts @@ -0,0 +1,3 @@ +export interface PdfToZipState { + files: File[]; +} diff --git a/src/js/types/posterize-type.ts b/src/js/types/posterize-type.ts new file mode 100644 index 0000000..031c046 --- /dev/null +++ b/src/js/types/posterize-type.ts @@ -0,0 +1,9 @@ +import * as pdfjsLib from 'pdfjs-dist'; + +export interface PosterizeState { + file: File | null; + pdfJsDoc: pdfjsLib.PDFDocumentProxy | null; + pdfBytes: Uint8Array | null; + pageSnapshots: Record; + currentPage: number; +} diff --git a/src/js/types/remove-metadata-type.ts b/src/js/types/remove-metadata-type.ts new file mode 100644 index 0000000..52dc35a --- /dev/null +++ b/src/js/types/remove-metadata-type.ts @@ -0,0 +1,3 @@ +export interface RemoveMetadataState { + file: File | null; +} diff --git a/src/js/types/remove-restrictions-type.ts b/src/js/types/remove-restrictions-type.ts new file mode 100644 index 0000000..772cc00 --- /dev/null +++ b/src/js/types/remove-restrictions-type.ts @@ -0,0 +1,3 @@ +export interface RemoveRestrictionsState { + file: File | null; +} diff --git a/src/js/types/reverse-pages-type.ts b/src/js/types/reverse-pages-type.ts new file mode 100644 index 0000000..02a7840 --- /dev/null +++ b/src/js/types/reverse-pages-type.ts @@ -0,0 +1,5 @@ +export interface ReverseState { + file: File | null; + pdfBytes: ArrayBuffer | null; + totalPages: number; +} diff --git a/src/js/types/rotate-pdf-type.ts b/src/js/types/rotate-pdf-type.ts new file mode 100644 index 0000000..01ec6ed --- /dev/null +++ b/src/js/types/rotate-pdf-type.ts @@ -0,0 +1,6 @@ +export interface RotateState { + file: File | null; + pdfBytes: ArrayBuffer | null; + totalPages: number; + pageRotations: Map; +} diff --git a/src/js/types/sanitize-pdf-type.ts b/src/js/types/sanitize-pdf-type.ts new file mode 100644 index 0000000..0da485c --- /dev/null +++ b/src/js/types/sanitize-pdf-type.ts @@ -0,0 +1,6 @@ +import { PDFDocument } from 'pdf-lib'; + +export interface SanitizePdfState { + file: File | null; + pdfDoc: PDFDocument | null; +} diff --git a/src/js/types/sign-pdf-type.ts b/src/js/types/sign-pdf-type.ts new file mode 100644 index 0000000..3085770 --- /dev/null +++ b/src/js/types/sign-pdf-type.ts @@ -0,0 +1,5 @@ +export interface SignPdfState { + file: File | null; + pdfBytes: ArrayBuffer | null; + signatureData: string | null; +} diff --git a/src/js/types/table-of-contents-type.ts b/src/js/types/table-of-contents-type.ts new file mode 100644 index 0000000..407ddbd --- /dev/null +++ b/src/js/types/table-of-contents-type.ts @@ -0,0 +1,18 @@ +export interface GenerateTOCMessage { + type: 'generateTOC'; + pdfBytes: ArrayBuffer; + title: string; + headerColor: string; + fontColor: string; + fontSize: number; +} + +export interface TOCSuccessResponse { + type: 'success'; + pdfBytes: ArrayBuffer; +} + +export interface TOCErrorResponse { + type: 'error'; + message: string; +} diff --git a/src/js/types/text-color-type.ts b/src/js/types/text-color-type.ts new file mode 100644 index 0000000..fe451b9 --- /dev/null +++ b/src/js/types/text-color-type.ts @@ -0,0 +1,6 @@ +import { PDFDocument as PDFLibDocument } from 'pdf-lib'; + +export interface TextColorState { + file: File | null; + pdfDoc: PDFLibDocument | null; +} diff --git a/src/js/types/validate-signature-type.ts b/src/js/types/validate-signature-type.ts new file mode 100644 index 0000000..4633848 --- /dev/null +++ b/src/js/types/validate-signature-type.ts @@ -0,0 +1,47 @@ +import forge from 'node-forge'; + +export interface SignatureValidationResult { + signatureIndex: number; + isValid: boolean; + signerName: string; + signerOrg?: string; + signerEmail?: string; + issuer: string; + issuerOrg?: string; + signatureDate?: Date; + validFrom: Date; + validTo: Date; + isExpired: boolean; + isSelfSigned: boolean; + isTrusted: boolean; + algorithms: { + digest: string; + signature: string; + }; + serialNumber: string; + reason?: string; + location?: string; + contactInfo?: string; + byteRange?: number[]; + coverageStatus: 'full' | 'partial' | 'unknown'; + errorMessage?: string; +} + +export interface ExtractedSignature { + index: number; + contents: Uint8Array; + byteRange: number[]; + reason?: string; + location?: string; + contactInfo?: string; + name?: string; + signingTime?: string; +} + +export interface ValidateSignatureState { + pdfFile: File | null; + pdfBytes: Uint8Array | null; + results: SignatureValidationResult[]; + trustedCertFile: File | null; + trustedCert: forge.pki.Certificate | null; +} diff --git a/src/js/types/view-metadata-type.ts b/src/js/types/view-metadata-type.ts new file mode 100644 index 0000000..8da1ce0 --- /dev/null +++ b/src/js/types/view-metadata-type.ts @@ -0,0 +1,4 @@ +export interface ViewMetadataState { + file: File | null; + metadata: Record; +} diff --git a/src/js/ui.ts b/src/js/ui.ts index dda62cb..427dbdb 100644 --- a/src/js/ui.ts +++ b/src/js/ui.ts @@ -44,9 +44,48 @@ export const dom = { warningConfirmBtn: document.getElementById('warning-confirm-btn'), }; -export const showLoader = (text = t('common.loading')) => { +export const showLoader = (text = t('common.loading'), progress?: number) => { if (dom.loaderText) dom.loaderText.textContent = text; - if (dom.loaderModal) dom.loaderModal.classList.remove('hidden'); + + // Add or update progress bar if progress is provided + const loaderModal = dom.loaderModal; + if (loaderModal) { + let progressBar = loaderModal.querySelector('.loader-progress-bar') as HTMLElement; + let progressContainer = loaderModal.querySelector('.loader-progress-container') as HTMLElement; + + if (progress !== undefined && progress >= 0) { + // Create progress container if it doesn't exist + if (!progressContainer) { + progressContainer = document.createElement('div'); + progressContainer.className = 'loader-progress-container w-64 mt-4'; + progressContainer.innerHTML = ` +
+
+
+

0%

+ `; + loaderModal.querySelector('.bg-gray-800')?.appendChild(progressContainer); + progressBar = progressContainer.querySelector('.loader-progress-bar') as HTMLElement; + } + + // Update progress + if (progressBar) { + progressBar.style.width = `${progress}%`; + } + const progressText = progressContainer.querySelector('.loader-progress-text'); + if (progressText) { + progressText.textContent = `${Math.round(progress)}%`; + } + progressContainer.classList.remove('hidden'); + } else { + // Hide progress bar if no progress provided + if (progressContainer) { + progressContainer.classList.add('hidden'); + } + } + + loaderModal.classList.remove('hidden'); + } }; export const hideLoader = () => { @@ -267,19 +306,19 @@ export const renderPageThumbnails = async (toolId: any, pdfDoc: any) => { // Event Listeners decrementBtn.addEventListener('click', (e) => { e.stopPropagation(); - let current = parseInt(angleInput.value) || 0; + const current = parseInt(angleInput.value) || 0; updateRotation(current - 1); }); incrementBtn.addEventListener('click', (e) => { e.stopPropagation(); - let current = parseInt(angleInput.value) || 0; + const current = parseInt(angleInput.value) || 0; updateRotation(current + 1); }); angleInput.addEventListener('change', (e) => { e.stopPropagation(); - let val = parseInt((e.target as HTMLInputElement).value) || 0; + const val = parseInt((e.target as HTMLInputElement).value) || 0; updateRotation(val); }); angleInput.addEventListener('click', (e) => e.stopPropagation()); @@ -292,7 +331,7 @@ export const renderPageThumbnails = async (toolId: any, pdfDoc: any) => { rotateBtn.innerHTML = ''; rotateBtn.addEventListener('click', (e) => { e.stopPropagation(); - let current = parseInt(angleInput.value) || 0; + const current = parseInt(angleInput.value) || 0; updateRotation(current + 90); }); @@ -433,8 +472,8 @@ const createFileInputHTML = (options = {}) => { -
` diff --git a/src/js/utils/csv-to-pdf.ts b/src/js/utils/csv-to-pdf.ts new file mode 100644 index 0000000..589ff59 --- /dev/null +++ b/src/js/utils/csv-to-pdf.ts @@ -0,0 +1,90 @@ +import { jsPDF } from 'jspdf'; +import autoTable from 'jspdf-autotable'; +import Papa from 'papaparse'; + +export interface CsvToPdfOptions { + onProgress?: (percent: number, message: string) => void; +} + +/** + * Convert a CSV file to PDF using jsPDF and autotable + */ +export async function convertCsvToPdf( + file: File, + options?: CsvToPdfOptions +): Promise { + const { onProgress } = options || {}; + + return new Promise((resolve, reject) => { + onProgress?.(10, 'Reading CSV file...'); + + Papa.parse(file, { + complete: (results) => { + try { + onProgress?.(50, 'Generating PDF...'); + + const data = results.data as string[][]; + + // Filter out empty rows + const filteredData = data.filter(row => + row.some(cell => cell && cell.trim() !== '') + ); + + if (filteredData.length === 0) { + reject(new Error('CSV file is empty')); + return; + } + + // Create PDF document + const doc = new jsPDF({ + orientation: 'landscape', // Better for wide tables + unit: 'mm', + format: 'a4' + }); + + // Extract headers (first row) and data + const headers = filteredData[0]; + const rows = filteredData.slice(1); + + onProgress?.(70, 'Creating table...'); + + // Generate table + autoTable(doc, { + head: [headers], + body: rows, + startY: 20, + styles: { + fontSize: 9, + cellPadding: 3, + overflow: 'linebreak', + cellWidth: 'wrap', + }, + headStyles: { + fillColor: [41, 128, 185], // Nice blue header + textColor: 255, + fontStyle: 'bold', + }, + alternateRowStyles: { + fillColor: [245, 245, 245], // Light gray for alternate rows + }, + margin: { top: 20, left: 10, right: 10 }, + theme: 'striped', + }); + + onProgress?.(90, 'Finalizing PDF...'); + + // Get PDF as blob + const pdfBlob = doc.output('blob'); + + onProgress?.(100, 'Complete!'); + resolve(pdfBlob); + } catch (error) { + reject(error); + } + }, + error: (error) => { + reject(new Error(`Failed to parse CSV: ${error.message}`)); + }, + }); + }); +} diff --git a/src/js/utils/full-width.ts b/src/js/utils/full-width.ts index efc5c89..4a07d68 100644 --- a/src/js/utils/full-width.ts +++ b/src/js/utils/full-width.ts @@ -2,7 +2,7 @@ // This script applies the full-width preference from localStorage to page uploaders export function initFullWidthMode() { - const savedFullWidth = localStorage.getItem('fullWidthMode') === 'true'; + const savedFullWidth = localStorage.getItem('fullWidthMode') !== 'false'; if (savedFullWidth) { applyFullWidthMode(true); diff --git a/src/js/utils/ghostscript-loader.ts b/src/js/utils/ghostscript-loader.ts new file mode 100644 index 0000000..1f56384 --- /dev/null +++ b/src/js/utils/ghostscript-loader.ts @@ -0,0 +1,452 @@ +/** + * PDF/A Conversion using Ghostscript WASM + * * Converts PDFs to PDF/A-1b, PDF/A-2b, or PDF/A-3b format. + */ + +import loadWASM from '@bentopdf/gs-wasm'; +import { getWasmBaseUrl, fetchWasmFile } from '../config/wasm-cdn-config.js'; +import { PDFDocument, PDFDict, PDFName, PDFArray } from 'pdf-lib'; + +interface GhostscriptModule { + FS: { + writeFile(path: string, data: Uint8Array | string): void; + readFile(path: string, opts?: { encoding?: string }): Uint8Array; + unlink(path: string): void; + stat(path: string): { size: number }; + }; + callMain(args: string[]): number; +} + +export type PdfALevel = 'PDF/A-1b' | 'PDF/A-2b' | 'PDF/A-3b'; + +let cachedGsModule: GhostscriptModule | null = null; + +export function setCachedGsModule(module: GhostscriptModule): void { + cachedGsModule = module; +} + +export function getCachedGsModule(): GhostscriptModule | null { + return cachedGsModule; +} + +export async function convertToPdfA( + pdfData: Uint8Array, + level: PdfALevel = 'PDF/A-2b', + onProgress?: (msg: string) => void +): Promise { + onProgress?.('Loading Ghostscript...'); + + let gs: GhostscriptModule; + + if (cachedGsModule) { + gs = cachedGsModule; + } else { + const gsBaseUrl = getWasmBaseUrl('ghostscript'); + gs = (await loadWASM({ + locateFile: (path: string) => { + if (path.endsWith('.wasm')) { + return gsBaseUrl + 'gs.wasm'; + } + return path; + }, + print: (text: string) => console.log('[GS]', text), + printErr: (text: string) => console.error('[GS Error]', text), + })) as GhostscriptModule; + cachedGsModule = gs; + } + + const pdfaMap: Record = { + 'PDF/A-1b': '1', + 'PDF/A-2b': '2', + 'PDF/A-3b': '3', + }; + + const inputPath = '/tmp/input.pdf'; + const outputPath = '/tmp/output.pdf'; + const iccPath = '/tmp/pdfa.icc'; + const pdfaDefPath = '/tmp/pdfa.ps'; + + gs.FS.writeFile(inputPath, pdfData); + console.log('[Ghostscript] Input file size:', pdfData.length); + + onProgress?.(`Converting to ${level}...`); + + try { + const iccFileName = 'sRGB_IEC61966-2-1_no_black_scaling.icc'; + const response = await fetchWasmFile('ghostscript', iccFileName); + + if (!response.ok) { + throw new Error( + `Failed to fetch ICC profile: ${iccFileName}. Ensure it is in your assets folder.` + ); + } + + const iccData = new Uint8Array(await response.arrayBuffer()); + console.log( + '[Ghostscript] sRGB v2 ICC profile loaded:', + iccData.length, + 'bytes' + ); + + gs.FS.writeFile(iccPath, iccData); + console.log('[Ghostscript] sRGB ICC profile written to FS:', iccPath); + + const iccHex = Array.from(iccData) + .map((b) => b.toString(16).padStart(2, '0')) + .join(''); + console.log('[Ghostscript] ICC profile hex length:', iccHex.length); + + const pdfaSubtype = level === 'PDF/A-1b' ? '/GTS_PDFA1' : '/GTS_PDFA'; + + const pdfaPS = `%! +% PDF/A definition file for ${level} + +% Define the ICC profile stream object with embedded hex data +[/_objdef {icc_PDFA} /type /stream /OBJ pdfmark +[{icc_PDFA} << /N 3 >> /PUT pdfmark +[{icc_PDFA} <${iccHex}> /PUT pdfmark + +% Define the OutputIntent dictionary +[/_objdef {OutputIntent_PDFA} /type /dict /OBJ pdfmark +[{OutputIntent_PDFA} << + /Type /OutputIntent + /S ${pdfaSubtype} + /DestOutputProfile {icc_PDFA} + /OutputConditionIdentifier (sRGB IEC61966-2.1) + /Info (sRGB IEC61966-2.1) + /RegistryName (http://www.color.org) +>> /PUT pdfmark + +% Attach OutputIntent to the document Catalog +[{Catalog} << /OutputIntents [ {OutputIntent_PDFA} ] >> /PUT pdfmark +`; + + gs.FS.writeFile(pdfaDefPath, pdfaPS); + console.log( + '[Ghostscript] PDFA PostScript created with embedded ICC hex data' + ); + } catch (e) { + console.error('[Ghostscript] Failed to setup PDF/A assets:', e); + throw new Error('Conversion failed: could not create PDF/A definition'); + } + + const args = [ + '-dNOSAFER', + '-dBATCH', + '-dNOPAUSE', + '-sDEVICE=pdfwrite', + `-dPDFA=${pdfaMap[level]}`, + '-dPDFACompatibilityPolicy=1', + `-dCompatibilityLevel=${level === 'PDF/A-1b' ? '1.4' : '1.7'}`, + '-sColorConversionStrategy=UseDeviceIndependentColor', + '-sICCProfilesDir=/tmp/', + `-sOutputICCProfile=${iccPath}`, + `-sDefaultRGBProfile=${iccPath}`, + `-sBlendColorProfile=${iccPath}`, + '-dCompressPages=true', + '-dWriteObjStms=false', + '-dWriteXRefStm=false', + '-dEmbedAllFonts=true', + '-dSubsetFonts=true', + '-dAutoRotatePages=/None', + `-sOutputFile=${outputPath}`, + pdfaDefPath, + inputPath, + ]; + + console.log('[Ghostscript] Running PDF/A conversion...'); + try { + console.log('[Ghostscript] Checking version:'); + gs.callMain(['--version']); + } catch (e) { + console.warn('[Ghostscript] Could not check version:', e); + } + + let exitCode: number; + try { + exitCode = gs.callMain(args); + } catch (e) { + console.error('[Ghostscript] Exception:', e); + throw new Error(`Ghostscript threw an exception: ${e}`); + } + + console.log('[Ghostscript] Exit code:', exitCode); + + if (exitCode !== 0) { + try { + gs.FS.unlink(inputPath); + } catch { + /* ignore */ + } + try { + gs.FS.unlink(outputPath); + } catch { + /* ignore */ + } + try { + gs.FS.unlink(iccPath); + } catch { + /* ignore */ + } + try { + gs.FS.unlink(pdfaDefPath); + } catch { + /* ignore */ + } + throw new Error(`Ghostscript conversion failed with exit code ${exitCode}`); + } + + // Read output + let output: Uint8Array; + try { + const stat = gs.FS.stat(outputPath); + console.log('[Ghostscript] Output file size:', stat.size); + output = gs.FS.readFile(outputPath); + } catch (e) { + console.error('[Ghostscript] Failed to read output:', e); + throw new Error('Ghostscript did not produce output file'); + } + + // Cleanup + try { + gs.FS.unlink(inputPath); + } catch { + /* ignore */ + } + try { + gs.FS.unlink(outputPath); + } catch { + /* ignore */ + } + try { + gs.FS.unlink(iccPath); + } catch { + /* ignore */ + } + try { + gs.FS.unlink(pdfaDefPath); + } catch { + /* ignore */ + } + + if (level !== 'PDF/A-1b') { + onProgress?.('Post-processing for transparency compliance...'); + console.log( + '[Ghostscript] Adding Group dictionaries to pages for transparency compliance...' + ); + + try { + output = await addPageGroupDictionaries(output); + console.log('[Ghostscript] Page Group dictionaries added successfully'); + } catch (e) { + console.error('[Ghostscript] Failed to add Group dictionaries:', e); + } + } + + return output; +} + +async function addPageGroupDictionaries( + pdfData: Uint8Array +): Promise { + const pdfDoc = await PDFDocument.load(pdfData, { + ignoreEncryption: true, + updateMetadata: false, + }); + + const catalog = pdfDoc.catalog; + const outputIntentsArray = catalog.lookup(PDFName.of('OutputIntents')); + + let iccProfileRef: ReturnType = undefined; + + if (outputIntentsArray instanceof PDFArray) { + const firstIntent = outputIntentsArray.lookup(0); + if (firstIntent instanceof PDFDict) { + iccProfileRef = firstIntent.get(PDFName.of('DestOutputProfile')); + } + } + + const updateGroupCS = (groupDict: PDFDict) => { + if (!iccProfileRef) return; + + const currentCS = groupDict.get(PDFName.of('CS')); + + if (currentCS instanceof PDFName) { + const csName = currentCS.decodeText(); + if ( + csName === 'DeviceRGB' || + csName === 'DeviceGray' || + csName === 'DeviceCMYK' + ) { + const iccColorSpace = pdfDoc.context.obj([ + PDFName.of('ICCBased'), + iccProfileRef, + ]); + groupDict.set(PDFName.of('CS'), iccColorSpace); + } + } else if (!currentCS) { + const iccColorSpace = pdfDoc.context.obj([ + PDFName.of('ICCBased'), + iccProfileRef, + ]); + groupDict.set(PDFName.of('CS'), iccColorSpace); + } + }; + + const pages = pdfDoc.getPages(); + for (const page of pages) { + const pageDict = page.node; + + const existingGroup = pageDict.lookup(PDFName.of('Group')); + if (existingGroup) { + if (existingGroup instanceof PDFDict) { + updateGroupCS(existingGroup); + } + } else if (iccProfileRef) { + const colorSpace = pdfDoc.context.obj([ + PDFName.of('ICCBased'), + iccProfileRef, + ]); + const groupDict = pdfDoc.context.obj({ + Type: 'Group', + S: 'Transparency', + I: false, + K: false, + }); + (groupDict as PDFDict).set(PDFName.of('CS'), colorSpace); + pageDict.set(PDFName.of('Group'), groupDict); + } + } + + if (iccProfileRef) { + pdfDoc.context.enumerateIndirectObjects().forEach(([ref, obj]) => { + if ( + obj instanceof PDFDict || + (obj && typeof obj === 'object' && 'dict' in obj) + ) { + const dict = + 'dict' in obj ? (obj as { dict: PDFDict }).dict : (obj as PDFDict); + + const subtype = dict.get(PDFName.of('Subtype')); + if (subtype instanceof PDFName && subtype.decodeText() === 'Form') { + const group = dict.lookup(PDFName.of('Group')); + if (group instanceof PDFDict) { + updateGroupCS(group); + } + } + } + }); + } + + return await pdfDoc.save({ + useObjectStreams: false, + addDefaultPage: false, + updateFieldAppearances: false, + }); +} + +export async function convertFileToPdfA( + file: File, + level: PdfALevel = 'PDF/A-2b', + onProgress?: (msg: string) => void +): Promise { + const arrayBuffer = await file.arrayBuffer(); + const pdfData = new Uint8Array(arrayBuffer); + const result = await convertToPdfA(pdfData, level, onProgress); + const copy = new Uint8Array(result.length); + copy.set(result); + return new Blob([copy], { type: 'application/pdf' }); +} + +export async function convertFontsToOutlines( + pdfData: Uint8Array, + onProgress?: (msg: string) => void +): Promise { + onProgress?.('Loading Ghostscript...'); + + let gs: GhostscriptModule; + + if (cachedGsModule) { + gs = cachedGsModule; + } else { + const gsBaseUrl = getWasmBaseUrl('ghostscript'); + gs = (await loadWASM({ + locateFile: (path: string) => { + if (path.endsWith('.wasm')) { + return gsBaseUrl + 'gs.wasm'; + } + return path; + }, + print: (text: string) => console.log('[GS]', text), + printErr: (text: string) => console.error('[GS Error]', text), + })) as GhostscriptModule; + cachedGsModule = gs; + } + + const inputPath = '/tmp/input.pdf'; + const outputPath = '/tmp/output.pdf'; + + gs.FS.writeFile(inputPath, pdfData); + + onProgress?.('Converting fonts to outlines...'); + + const args = [ + '-dNOSAFER', + '-dBATCH', + '-dNOPAUSE', + '-sDEVICE=pdfwrite', + '-dNoOutputFonts', + '-dCompressPages=true', + '-dAutoRotatePages=/None', + `-sOutputFile=${outputPath}`, + inputPath, + ]; + + let exitCode: number; + try { + exitCode = gs.callMain(args); + } catch (e) { + try { + gs.FS.unlink(inputPath); + } catch {} + throw new Error(`Ghostscript threw an exception: ${e}`); + } + + if (exitCode !== 0) { + try { + gs.FS.unlink(inputPath); + } catch {} + try { + gs.FS.unlink(outputPath); + } catch {} + throw new Error(`Ghostscript conversion failed with exit code ${exitCode}`); + } + + let output: Uint8Array; + try { + output = gs.FS.readFile(outputPath); + } catch (e) { + throw new Error('Ghostscript did not produce output file'); + } + + try { + gs.FS.unlink(inputPath); + } catch {} + try { + gs.FS.unlink(outputPath); + } catch {} + + return output; +} + +export async function convertFileToOutlines( + file: File, + onProgress?: (msg: string) => void +): Promise { + const arrayBuffer = await file.arrayBuffer(); + const pdfData = new Uint8Array(arrayBuffer); + const result = await convertFontsToOutlines(pdfData, onProgress); + const copy = new Uint8Array(result.length); + copy.set(result); + return new Blob([copy], { type: 'application/pdf' }); +} diff --git a/src/js/utils/helpers.ts b/src/js/utils/helpers.ts index 25e9cd4..b5afd5f 100644 --- a/src/js/utils/helpers.ts +++ b/src/js/utils/helpers.ts @@ -2,8 +2,7 @@ import createModule from '@neslinesli93/qpdf-wasm'; import { showLoader, hideLoader, showAlert } from '../ui.js'; import { createIcons } from 'lucide'; import { state, resetState } from '../state.js'; -import * as pdfjsLib from 'pdfjs-dist' - +import * as pdfjsLib from 'pdfjs-dist'; const STANDARD_SIZES = { A4: { width: 595.28, height: 841.89 }, @@ -50,14 +49,14 @@ export function convertPoints(points: any, unit: any) { // Convert hex color to RGB export function hexToRgb(hex: string): { r: number; g: number; b: number } { - const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { - r: parseInt(result[1], 16) / 255, - g: parseInt(result[2], 16) / 255, - b: parseInt(result[3], 16) / 255, - } - : { r: 0, g: 0, b: 0 } + r: parseInt(result[1], 16) / 255, + g: parseInt(result[2], 16) / 255, + b: parseInt(result[3], 16) / 255, + } + : { r: 0, g: 0, b: 0 }; } export const formatBytes = (bytes: any, decimals = 1) => { @@ -89,7 +88,10 @@ export const readFileAsArrayBuffer = (file: any) => { }); }; -export function parsePageRanges(rangeString: string, totalPages: number): number[] { +export function parsePageRanges( + rangeString: string, + totalPages: number +): number[] { if (!rangeString || rangeString.trim() === '') { return Array.from({ length: totalPages }, (_, i) => i); } @@ -128,11 +130,9 @@ export function parsePageRanges(rangeString: string, totalPages: number): number } } - return Array.from(indices).sort((a, b) => a - b); } - /** * Formats an ISO 8601 date string (e.g., "2008-02-21T17:15:56-08:00") * into a localized, human-readable string. @@ -198,7 +198,7 @@ export function formatStars(num: number) { return (num / 1000).toFixed(1) + 'K'; } return num.toLocaleString(); -}; +} /** * Truncates a filename to a maximum length, adding ellipsis if needed. @@ -207,14 +207,18 @@ export function formatStars(num: number) { * @param maxLength - Maximum length (default: 30) * @returns Truncated filename with ellipsis if needed */ -export function truncateFilename(filename: string, maxLength: number = 25): string { +export function truncateFilename( + filename: string, + maxLength: number = 25 +): string { if (filename.length <= maxLength) { return filename; } const lastDotIndex = filename.lastIndexOf('.'); const extension = lastDotIndex !== -1 ? filename.substring(lastDotIndex) : ''; - const nameWithoutExt = lastDotIndex !== -1 ? filename.substring(0, lastDotIndex) : filename; + const nameWithoutExt = + lastDotIndex !== -1 ? filename.substring(0, lastDotIndex) : filename; const availableLength = maxLength - extension.length - 3; // 3 for '...' @@ -225,7 +229,10 @@ export function truncateFilename(filename: string, maxLength: number = 25): stri return nameWithoutExt.substring(0, availableLength) + '...' + extension; } -export function formatShortcutDisplay(shortcut: string, isMac: boolean): string { +export function formatShortcutDisplay( + shortcut: string, + isMac: boolean +): string { if (!shortcut) return ''; return shortcut .replace('mod', isMac ? '⌘' : 'Ctrl') @@ -233,7 +240,7 @@ export function formatShortcutDisplay(shortcut: string, isMac: boolean): string .replace('alt', isMac ? '⌥' : 'Alt') .replace('shift', 'Shift') .split('+') - .map(k => k.charAt(0).toUpperCase() + k.slice(1)) + .map((k) => k.charAt(0).toUpperCase() + k.slice(1)) .join(isMac ? '' : '+'); } @@ -263,7 +270,7 @@ export function resetAndReloadTool(preResetCallback?: () => void) { export function getPDFDocument(src: any) { let params = src; - // Handle different input types similar to how getDocument handles them, + // Handle different input types similar to how getDocument handles them, // but we ensure we have an object to attach wasmUrl to. if (typeof src === 'string') { params = { url: src }; @@ -283,3 +290,173 @@ export function getPDFDocument(src: any) { wasmUrl: import.meta.env.BASE_URL + 'pdfjs-viewer/wasm/', }); } + +/** + * Escape HTML special characters to prevent XSS + * @param text - The text to escape + * @returns The escaped text + */ +export function escapeHtml(text: string): string { + const map: Record = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + }; + return text.replace(/[&<>"']/g, (m) => map[m]); +} + +export function uint8ArrayToBase64(bytes: Uint8Array): string { + const CHUNK_SIZE = 0x8000; + const chunks: string[] = []; + for (let i = 0; i < bytes.length; i += CHUNK_SIZE) { + const chunk = bytes.subarray(i, Math.min(i + CHUNK_SIZE, bytes.length)); + chunks.push(String.fromCharCode(...chunk)); + } + return btoa(chunks.join('')); +} + +export function sanitizeEmailHtml(html: string): string { + if (!html) return html; + + let sanitized = html; + + sanitized = sanitized.replace(/]*>[\s\S]*?<\/head>/gi, ''); + sanitized = sanitized.replace(/]*>[\s\S]*?<\/style>/gi, ''); + sanitized = sanitized.replace(/]*>[\s\S]*?<\/script>/gi, ''); + sanitized = sanitized.replace(/]*>/gi, ''); + sanitized = sanitized.replace(/\s+style=["'][^"']*["']/gi, ''); + sanitized = sanitized.replace(/\s+class=["'][^"']*["']/gi, ''); + sanitized = sanitized.replace(/\s+data-[a-z-]+=["'][^"']*["']/gi, ''); + sanitized = sanitized.replace( + /]*(?:width=["']1["'][^>]*height=["']1["']|height=["']1["'][^>]*width=["']1["'])[^>]*\/?>/gi, + '' + ); + sanitized = sanitized.replace( + /href=["']https?:\/\/[^"']*safelinks\.protection\.outlook\.com[^"']*url=([^&"']+)[^"']*["']/gi, + (match, encodedUrl) => { + try { + const decodedUrl = decodeURIComponent(encodedUrl); + return `href="${decodedUrl}"`; + } catch { + return match; + } + } + ); + sanitized = sanitized.replace(/\s+originalsrc=["'][^"']*["']/gi, ''); + sanitized = sanitized.replace( + /href=["']([^"']{500,})["']/gi, + (match, url) => { + const baseUrl = url.split('?')[0]; + if (baseUrl && baseUrl.length < 200) { + return `href="${baseUrl}"`; + } + return `href="${url.substring(0, 200)}"`; + } + ); + + sanitized = sanitized.replace( + /\s+(cellpadding|cellspacing|bgcolor|border|valign|align|width|height|role|dir|id)=["'][^"']*["']/gi, + '' + ); + sanitized = sanitized.replace(/<\/?table[^>]*>/gi, '
'); + sanitized = sanitized.replace(/<\/?tbody[^>]*>/gi, ''); + sanitized = sanitized.replace(/<\/?thead[^>]*>/gi, ''); + sanitized = sanitized.replace(/<\/?tfoot[^>]*>/gi, ''); + sanitized = sanitized.replace(/]*>/gi, '
'); + sanitized = sanitized.replace(/<\/tr>/gi, '
'); + sanitized = sanitized.replace(/]*>/gi, ' '); + sanitized = sanitized.replace(/<\/td>/gi, ' '); + sanitized = sanitized.replace(/]*>/gi, ' '); + sanitized = sanitized.replace(/<\/th>/gi, ' '); + sanitized = sanitized.replace(/
\s*<\/div>/gi, ''); + sanitized = sanitized.replace(/\s*<\/span>/gi, ''); + sanitized = sanitized.replace(/(
)+/gi, '
'); + sanitized = sanitized.replace(/(<\/div>)+/gi, '
'); + sanitized = sanitized.replace( + /]*href=["']\s*["'][^>]*>([^<]*)<\/a>/gi, + '$1' + ); + + const MAX_HTML_SIZE = 100000; + if (sanitized.length > MAX_HTML_SIZE) { + const truncateAt = sanitized.lastIndexOf('
', MAX_HTML_SIZE); + if (truncateAt > MAX_HTML_SIZE / 2) { + sanitized = sanitized.substring(0, truncateAt) + '
'; + } else { + sanitized = sanitized.substring(0, MAX_HTML_SIZE) + '...'; + } + } + + return sanitized; +} + +/** + * Formats a raw RFC 2822 date string into a nicer human-readable format, + * while preserving the original timezone and time. + * Example input: "Sun, 8 Jan 2017 20:37:44 +0200" + * Example output: "Sunday, January 8, 2017 at 8:37 PM (+0200)" + */ +export function formatRawDate(raw: string): string { + try { + const match = raw.match( + /([A-Za-z]{3}),\s+(\d{1,2})\s+([A-Za-z]{3})\s+(\d{4})\s+(\d{2}):(\d{2})(?::(\d{2}))?\s+([+-]\d{4})/ + ); + + if (match) { + const [ + , + dayAbbr, + dom, + monthAbbr, + year, + hoursStr, + minsStr, + secsStr, + timezone, + ] = match; + + const days: Record = { + Sun: 'Sunday', + Mon: 'Monday', + Tue: 'Tuesday', + Wed: 'Wednesday', + Thu: 'Thursday', + Fri: 'Friday', + Sat: 'Saturday', + }; + const months: Record = { + Jan: 'January', + Feb: 'February', + Mar: 'March', + Apr: 'April', + May: 'May', + Jun: 'June', + Jul: 'July', + Aug: 'August', + Sep: 'September', + Oct: 'October', + Nov: 'November', + Dec: 'December', + }; + + const fullDay = days[dayAbbr] || dayAbbr; + const fullMonth = months[monthAbbr] || monthAbbr; + + let hours = parseInt(hoursStr, 10); + const ampm = hours >= 12 ? 'PM' : 'AM'; + hours = hours % 12; + hours = hours ? hours : 12; + const tzSign = timezone.substring(0, 1); + const tzHours = timezone.substring(1, 3); + const tzMins = timezone.substring(3, 5); + const formattedTz = `UTC${tzSign}${tzHours}:${tzMins}`; + + return `${fullDay}, ${fullMonth} ${dom}, ${year} at ${hours}:${minsStr} ${ampm} (${formattedTz})`; + } + } catch (e) { + // Fallback to raw string if parsing fails + } + return raw; +} diff --git a/src/js/utils/hocr-transform.ts b/src/js/utils/hocr-transform.ts new file mode 100644 index 0000000..eba2772 --- /dev/null +++ b/src/js/utils/hocr-transform.ts @@ -0,0 +1,266 @@ +import { + BBox, + OcrLine, + OcrPage, + OcrWord, + WordTransform, + Baseline, +} from '@/types'; + +const BBOX_PATTERN = /bbox\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/; +const BASELINE_PATTERN = /baseline\s+([-+]?\d*\.?\d*)\s+([-+]?\d+)/; +const TEXTANGLE_PATTERN = /textangle\s+([-+]?\d*\.?\d*)/; + +export function parseBBox(title: string): BBox | null { + const match = title.match(BBOX_PATTERN); + if (!match) return null; + + return { + x0: parseInt(match[1], 10), + y0: parseInt(match[2], 10), + x1: parseInt(match[3], 10), + y1: parseInt(match[4], 10), + }; +} + +export function parseBaseline(title: string): Baseline { + const match = title.match(BASELINE_PATTERN); + if (!match) { + return { slope: 0, intercept: 0 }; + } + + return { + slope: parseFloat(match[1]) || 0, + intercept: parseInt(match[2], 10) || 0, + }; +} + +export function parseTextangle(title: string): number { + const match = title.match(TEXTANGLE_PATTERN); + if (!match) return 0; + return parseFloat(match[1]) || 0; +} + +export function getTextDirection(element: Element): 'ltr' | 'rtl' { + const dir = element.getAttribute('dir'); + return dir === 'rtl' ? 'rtl' : 'ltr'; +} + +export function shouldInjectWordBreaks(element: Element): boolean { + const lang = element.getAttribute('lang') || ''; + const cjkLangs = ['chi_sim', 'chi_tra', 'jpn', 'kor', 'zh', 'ja', 'ko']; + return !cjkLangs.includes(lang); +} + +export function normalizeText(text: string): string { + return text.normalize('NFKC'); +} + +export function parseHocrDocument(hocrText: string): OcrPage { + const parser = new DOMParser(); + const doc = parser.parseFromString(hocrText, 'text/html'); + + let width = 0; + let height = 0; + const pageDiv = doc.querySelector('.ocr_page'); + if (pageDiv) { + const title = pageDiv.getAttribute('title') || ''; + const bbox = parseBBox(title); + if (bbox) { + width = bbox.x1 - bbox.x0; + height = bbox.y1 - bbox.y0; + } + } + + const lines: OcrLine[] = []; + + const lineClasses = [ + 'ocr_line', + 'ocr_textfloat', + 'ocr_header', + 'ocr_caption', + ]; + const lineSelectors = lineClasses.map((c) => `.${c}`).join(', '); + const lineElements = doc.querySelectorAll(lineSelectors); + + if (lineElements.length > 0) { + lineElements.forEach((lineEl) => { + const line = parseHocrLine(lineEl); + if (line && line.words.length > 0) { + lines.push(line); + } + }); + } else { + const wordElements = doc.querySelectorAll('.ocrx_word'); + if (wordElements.length > 0) { + const words = parseWordsFromElements(wordElements); + if (words.length > 0) { + const allBBox = calculateBoundingBox(words.map((w) => w.bbox)); + lines.push({ + bbox: allBBox, + baseline: { slope: 0, intercept: 0 }, + textangle: 0, + words, + direction: 'ltr', + injectWordBreaks: true, + }); + } + } + } + + return { width, height, dpi: 72, lines }; +} + +function parseHocrLine(lineElement: Element): OcrLine | null { + const title = lineElement.getAttribute('title') || ''; + const bbox = parseBBox(title); + + if (!bbox) return null; + + const baseline = parseBaseline(title); + const textangle = parseTextangle(title); + + const parent = lineElement.closest('.ocr_par') || lineElement.parentElement; + const direction = parent ? getTextDirection(parent) : 'ltr'; + const injectWordBreaks = parent ? shouldInjectWordBreaks(parent) : true; + const wordElements = lineElement.querySelectorAll('.ocrx_word'); + const words = parseWordsFromElements(wordElements); + + return { + bbox, + baseline, + textangle, + words, + direction, + injectWordBreaks, + }; +} + +function parseWordsFromElements(wordElements: NodeListOf): OcrWord[] { + const words: OcrWord[] = []; + + wordElements.forEach((wordEl) => { + const title = wordEl.getAttribute('title') || ''; + const text = normalizeText((wordEl.textContent || '').trim()); + + if (!text) return; + + const bbox = parseBBox(title); + if (!bbox) return; + + const confMatch = title.match(/x_wconf\s+(\d+)/); + const confidence = confMatch ? parseInt(confMatch[1], 10) : 0; + + words.push({ + text, + bbox, + confidence, + }); + }); + + return words; +} + +function calculateBoundingBox(bboxes: BBox[]): BBox { + if (bboxes.length === 0) { + return { x0: 0, y0: 0, x1: 0, y1: 0 }; + } + + return { + x0: Math.min(...bboxes.map((b) => b.x0)), + y0: Math.min(...bboxes.map((b) => b.y0)), + x1: Math.max(...bboxes.map((b) => b.x1)), + y1: Math.max(...bboxes.map((b) => b.y1)), + }; +} + +/** + * Calculate the transformation parameters for drawing a word + * + * pdf-lib doesn't support horizontal text scaling (Tz operator), + * we calculate a font size that makes the text width exactly match the word bbox width. + * + * @param word - The word to position + * @param line - The line containing this word + * @param pageHeight - Height of the page in pixels (for coordinate flip) + * @param fontWidthFn - Function to calculate text width at a given font size + * @returns Transform parameters for pdf-lib + */ +export function calculateWordTransform( + word: OcrWord, + line: OcrLine, + pageHeight: number, + fontWidthFn: (text: string, fontSize: number) => number +): WordTransform { + const wordBBox = word.bbox; + const wordWidth = wordBBox.x1 - wordBBox.x0; + const wordHeight = wordBBox.y1 - wordBBox.y0; + + let fontSize = wordHeight; + const maxIterations = 10; + + for (let i = 0; i < maxIterations; i++) { + const currentWidth = fontWidthFn(word.text, fontSize); + if (currentWidth <= 0) break; + + const ratio = wordWidth / currentWidth; + const newFontSize = fontSize * ratio; + + if (Math.abs(newFontSize - fontSize) / fontSize < 0.01) { + fontSize = newFontSize; + break; + } + fontSize = newFontSize; + } + + fontSize = Math.max(1, Math.min(fontSize, wordHeight * 2)); + + const fontWidth = fontWidthFn(word.text, fontSize); + const horizontalScale = fontWidth > 0 ? wordWidth / fontWidth : 1; + + const slopeAngle = Math.atan(line.baseline.slope) * (180 / Math.PI); + const rotation = -line.textangle + slopeAngle; + + const x = wordBBox.x0; + + // pdf-lib draws text from baseline, so we position at word bottom + const y = pageHeight - wordBBox.y1; + + return { + x, + y, + fontSize, + horizontalScale, + rotation, + }; +} + +export function calculateSpaceTransform( + prevWord: OcrWord, + nextWord: OcrWord, + line: OcrLine, + pageHeight: number, + spaceWidthFn: (fontSize: number) => number +): { x: number; y: number; horizontalScale: number; fontSize: number } | null { + const lineHeight = line.bbox.y1 - line.bbox.y0; + const fontSize = Math.max(lineHeight + line.baseline.intercept, 1); + + const gapStart = prevWord.bbox.x1; + const gapEnd = nextWord.bbox.x0; + const gapWidth = gapEnd - gapStart; + + if (gapWidth <= 0) return null; + + const spaceWidth = spaceWidthFn(fontSize); + if (spaceWidth <= 0) return null; + + const horizontalScale = gapWidth / spaceWidth; + const baselineY = pageHeight - line.bbox.y1 - line.baseline.intercept; + + return { + x: gapStart, + y: baselineY, + horizontalScale, + fontSize, + }; +} diff --git a/src/js/utils/libreoffice-loader.ts b/src/js/utils/libreoffice-loader.ts new file mode 100644 index 0000000..54b5b73 --- /dev/null +++ b/src/js/utils/libreoffice-loader.ts @@ -0,0 +1,160 @@ +/** + * LibreOffice WASM Converter Wrapper + * + * Uses @matbee/libreoffice-converter package for document conversion. + * Handles progress tracking and provides simpler API. + */ + +import { WorkerBrowserConverter } from '@matbee/libreoffice-converter/browser'; + +const LIBREOFFICE_LOCAL_PATH = import.meta.env.BASE_URL + 'libreoffice-wasm/'; + +export interface LoadProgress { + phase: 'loading' | 'initializing' | 'converting' | 'complete' | 'ready'; + percent: number; + message: string; +} + +export type ProgressCallback = (progress: LoadProgress) => void; + +// Singleton for converter instance +let converterInstance: LibreOfficeConverter | null = null; + +export class LibreOfficeConverter { + private converter: WorkerBrowserConverter | null = null; + private initialized = false; + private initializing = false; + private basePath: string; + + constructor(basePath?: string) { + this.basePath = basePath || LIBREOFFICE_LOCAL_PATH; + } + + async initialize(onProgress?: ProgressCallback): Promise { + if (this.initialized) return; + + if (this.initializing) { + while (this.initializing) { + await new Promise(r => setTimeout(r, 100)); + } + return; + } + + + this.initializing = true; + let progressCallback = onProgress; // Store original callback + + try { + progressCallback?.({ phase: 'loading', percent: 0, message: 'Loading conversion engine...' }); + + this.converter = new WorkerBrowserConverter({ + sofficeJs: `${this.basePath}soffice.js`, + sofficeWasm: `${this.basePath}soffice.wasm.gz`, + sofficeData: `${this.basePath}soffice.data.gz`, + sofficeWorkerJs: `${this.basePath}soffice.worker.js`, + browserWorkerJs: `${this.basePath}browser.worker.global.js`, + verbose: false, + onProgress: (info: { phase: string; percent: number; message: string }) => { + if (progressCallback && !this.initialized) { + const simplifiedMessage = `Loading conversion engine (${Math.round(info.percent)}%)...`; + progressCallback({ + phase: info.phase as LoadProgress['phase'], + percent: info.percent, + message: simplifiedMessage + }); + } + }, + onReady: () => { + console.log('[LibreOffice] Ready!'); + }, + onError: (error: Error) => { + console.error('[LibreOffice] Error:', error); + }, + }); + + await this.converter.initialize(); + this.initialized = true; + + // Call completion message + progressCallback?.({ phase: 'ready', percent: 100, message: 'Conversion engine ready!' }); + + // Null out the callback to prevent any late-firing progress updates + progressCallback = undefined; + } finally { + this.initializing = false; + } + } + + isReady(): boolean { + return this.initialized && this.converter !== null; + } + + async convertToPdf(file: File): Promise { + if (!this.converter) { + throw new Error('Converter not initialized'); + } + + console.log(`[LibreOffice] Converting ${file.name} to PDF...`); + console.log(`[LibreOffice] File type: ${file.type}, Size: ${file.size} bytes`); + + try { + console.log(`[LibreOffice] Reading file as ArrayBuffer...`); + const arrayBuffer = await file.arrayBuffer(); + const uint8Array = new Uint8Array(arrayBuffer); + console.log(`[LibreOffice] File loaded, ${uint8Array.length} bytes`); + + console.log(`[LibreOffice] Calling converter.convert() with buffer...`); + const startTime = Date.now(); + + // Detect input format - critical for CSV to apply import filters + const ext = file.name.split('.').pop()?.toLowerCase() || ''; + console.log(`[LibreOffice] Detected format from extension: ${ext}`); + + const result = await this.converter.convert(uint8Array, { + outputFormat: 'pdf', + inputFormat: ext as any, // Explicitly specify format for CSV import filters + }, file.name); + + const duration = Date.now() - startTime; + console.log(`[LibreOffice] Conversion complete! Duration: ${duration}ms, Size: ${result.data.length} bytes`); + + // Create a copy to avoid SharedArrayBuffer type issues + const data = new Uint8Array(result.data); + return new Blob([data], { type: result.mimeType }); + } catch (error) { + console.error(`[LibreOffice] Conversion FAILED for ${file.name}:`, error); + console.error(`[LibreOffice] Error details:`, { + message: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined + }); + throw error; + } + } + + async wordToPdf(file: File): Promise { + return this.convertToPdf(file); + } + + async pptToPdf(file: File): Promise { + return this.convertToPdf(file); + } + + async excelToPdf(file: File): Promise { + return this.convertToPdf(file); + } + + async destroy(): Promise { + if (this.converter) { + await this.converter.destroy(); + } + this.converter = null; + this.initialized = false; + } +} + +export function getLibreOfficeConverter(basePath?: string): LibreOfficeConverter { + if (!converterInstance) { + converterInstance = new LibreOfficeConverter(basePath); + } + return converterInstance; +} diff --git a/src/js/utils/markdown-editor.ts b/src/js/utils/markdown-editor.ts new file mode 100644 index 0000000..a1a450f --- /dev/null +++ b/src/js/utils/markdown-editor.ts @@ -0,0 +1,970 @@ +import MarkdownIt from 'markdown-it'; +import hljs from 'highlight.js/lib/core'; +import javascript from 'highlight.js/lib/languages/javascript'; +import typescript from 'highlight.js/lib/languages/typescript'; +import python from 'highlight.js/lib/languages/python'; +import css from 'highlight.js/lib/languages/css'; +import xml from 'highlight.js/lib/languages/xml'; +import json from 'highlight.js/lib/languages/json'; +import bash from 'highlight.js/lib/languages/bash'; +import markdownLang from 'highlight.js/lib/languages/markdown'; +import sql from 'highlight.js/lib/languages/sql'; +import java from 'highlight.js/lib/languages/java'; +import csharp from 'highlight.js/lib/languages/csharp'; +import cpp from 'highlight.js/lib/languages/cpp'; +import go from 'highlight.js/lib/languages/go'; +import rust from 'highlight.js/lib/languages/rust'; +import yaml from 'highlight.js/lib/languages/yaml'; +import 'highlight.js/styles/github.css'; +import mermaid from 'mermaid'; +import sub from 'markdown-it-sub'; +import sup from 'markdown-it-sup'; +import footnote from 'markdown-it-footnote'; +import deflist from 'markdown-it-deflist'; +import abbr from 'markdown-it-abbr'; +import { full as emoji } from 'markdown-it-emoji'; +import ins from 'markdown-it-ins'; +import mark from 'markdown-it-mark'; +import taskLists from 'markdown-it-task-lists'; +import anchor from 'markdown-it-anchor'; +import tocDoneRight from 'markdown-it-toc-done-right'; +import { applyTranslations } from '../i18n/i18n'; + + + +// Register highlight.js languages +hljs.registerLanguage('javascript', javascript); +hljs.registerLanguage('js', javascript); +hljs.registerLanguage('typescript', typescript); +hljs.registerLanguage('ts', typescript); +hljs.registerLanguage('python', python); +hljs.registerLanguage('py', python); +hljs.registerLanguage('css', css); +hljs.registerLanguage('html', xml); +hljs.registerLanguage('xml', xml); +hljs.registerLanguage('json', json); +hljs.registerLanguage('bash', bash); +hljs.registerLanguage('sh', bash); +hljs.registerLanguage('shell', bash); +hljs.registerLanguage('markdown', markdownLang); +hljs.registerLanguage('md', markdownLang); +hljs.registerLanguage('sql', sql); +hljs.registerLanguage('java', java); +hljs.registerLanguage('csharp', csharp); +hljs.registerLanguage('cs', csharp); +hljs.registerLanguage('cpp', cpp); +hljs.registerLanguage('c', cpp); +hljs.registerLanguage('go', go); +hljs.registerLanguage('rust', rust); +hljs.registerLanguage('yaml', yaml); +hljs.registerLanguage('yml', yaml); + +export interface MarkdownEditorOptions { + /** Initial markdown content */ + initialContent?: string; + /** Callback when user wants to go back */ + onBack?: () => void; +} + +export interface MarkdownItOptions { + /** Enable HTML tags in source */ + html: boolean; + /** Convert '\n' in paragraphs into
*/ + breaks: boolean; + /** Autoconvert URL-like text to links */ + linkify: boolean; + /** Enable some language-neutral replacement + quotes beautification */ + typographer: boolean; + /** Highlight function for fenced code blocks */ + highlight?: (str: string, lang: string) => string; +} + +const DEFAULT_MARKDOWN = `# Welcome to BentoPDF Markdown Editor + +This is a **live preview** markdown editor with full plugin support. + +\${toc} + +## Basic Formatting + +- **Bold** and *italic* text +- ~~Strikethrough~~ text +- [Links](https://bentopdf.com) +- ==Highlighted text== using mark +- ++Inserted text++ using ins +- H~2~O for subscript +- E=mc^2^ for superscript + +## Task Lists + +- [x] Completed task +- [x] Another done item +- [ ] Pending task +- [ ] Future work + +## Emoji Support :rocket: + +Use emoji shortcodes: :smile: :heart: :thumbsup: :star: :fire: + +## Code with Syntax Highlighting + +\`\`\`javascript +function greet(name) { + console.log(\`Hello, \${name}!\`); + return { message: 'Welcome!' }; +} +\`\`\` + +\`\`\`python +def fibonacci(n): + if n <= 1: + return n + return fibonacci(n-1) + fibonacci(n-2) +\`\`\` + +## Tables + +| Feature | Supported | Notes | +|---------|:---------:|-------| +| Headers | ✓ | Multiple levels | +| Lists | ✓ | Ordered & unordered | +| Code | ✓ | With highlighting | +| Tables | ✓ | With alignment | +| Emoji | ✓ | :white_check_mark: | +| Mermaid | ✓ | Diagrams! | + +## Mermaid Diagrams + +### Flowchart + +\`\`\`mermaid +graph TD + A[Start] --> B{Decision} + B -->|Yes| C[OK] + B -->|No| D[Cancel] +\`\`\` + +### Sequence Diagram + +\`\`\`mermaid +sequenceDiagram + participant User + participant BentoPDF + participant Server + User->>BentoPDF: Upload PDF + BentoPDF->>BentoPDF: Process locally + BentoPDF-->>User: Download result + Note over BentoPDF: No server needed! +\`\`\` + +### Pie Chart + +\`\`\`mermaid +pie title PDF Tools Usage + "Merge" : 35 + "Compress" : 25 + "Convert" : 20 + "Edit" : 15 + "Other" : 5 +\`\`\` + +### Class Diagram + +\`\`\`mermaid +classDiagram + class PDFDocument { + +String title + +int pageCount + +merge() + +split() + +compress() + } + class Page { + +int number + +rotate() + +crop() + } + PDFDocument "1" --> "*" Page +\`\`\` + +### Gantt Chart + +\`\`\`mermaid +gantt + title Project Timeline + dateFormat YYYY-MM-DD + section Planning + Research :a1, 2024-01-01, 7d + Design :a2, after a1, 5d + section Development + Implementation :a3, after a2, 14d + Testing :a4, after a3, 7d +\`\`\` + +### Entity Relationship + +\`\`\`mermaid +erDiagram + USER ||--o{ DOCUMENT : uploads + DOCUMENT ||--|{ PAGE : contains + DOCUMENT { + string id + string name + date created + } + PAGE { + int number + string content + } +\`\`\` + +### Mindmap + +\`\`\`mermaid +mindmap + root((BentoPDF)) + Convert + Word to PDF + Excel to PDF + Image to PDF + Edit + Merge + Split + Compress + Secure + Encrypt + Sign + Watermark +\`\`\` + +## Footnotes + +Here's a sentence with a footnote[^1]. + +## Definition Lists + +Term 1 +: Definition for term 1 + +Term 2 +: Definition for term 2 +: Another definition for term 2 + +## Abbreviations + +The HTML specification is maintained by the W3C. + +*[HTML]: Hyper Text Markup Language +*[W3C]: World Wide Web Consortium + +--- + +Start editing to see the magic happen! + +[^1]: This is the footnote content. +`; + +export class MarkdownEditor { + private container: HTMLElement; + private md: MarkdownIt; + private editor: HTMLTextAreaElement | null = null; + private preview: HTMLElement | null = null; + private onBack?: () => void; + private syncScroll: boolean = false; + private isSyncing: boolean = false; + private mermaidInitialized: boolean = false; + private mdOptions: MarkdownItOptions = { + html: true, + breaks: false, + linkify: true, + typographer: true + }; + + constructor(container: HTMLElement, options: MarkdownEditorOptions) { + this.container = container; + this.onBack = options.onBack; + + this.initMermaid(); + this.md = this.createMarkdownIt(); + this.configureLinkRenderer(); + + this.render(); + + if (options.initialContent) { + this.setContent(options.initialContent); + } else { + this.setContent(DEFAULT_MARKDOWN); + } + } + + private initMermaid(): void { + if (!this.mermaidInitialized) { + mermaid.initialize({ + startOnLoad: false, + theme: 'default', + securityLevel: 'loose', + fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif' + }); + this.mermaidInitialized = true; + } + } + + private configureLinkRenderer(): void { + // Override link renderer to add target="_blank" and rel="noopener" + const defaultRender = this.md.renderer.rules.link_open || + ((tokens: any[], idx: number, options: any, _env: any, self: any) => self.renderToken(tokens, idx, options)); + + this.md.renderer.rules.link_open = (tokens: any[], idx: number, options: any, env: any, self: any) => { + const token = tokens[idx]; + token.attrSet('target', '_blank'); + token.attrSet('rel', 'noopener noreferrer'); + return defaultRender(tokens, idx, options, env, self); + }; + } + + private render(): void { + this.container.innerHTML = ` +
+
+
+
+ + +
+ +
+ +
+ + + +
+
+ +
+
+
+ Markdown +
+ +
+
+
+ Preview +
+
+
+
+
+
+ + + + `; + + this.editor = document.getElementById('mdTextarea') as HTMLTextAreaElement; + this.preview = document.getElementById('mdPreview') as HTMLElement; + + this.setupEventListeners(); + this.applyI18n(); + + // Initialize Lucide icons + if (typeof (window as any).lucide !== 'undefined') { + (window as any).lucide.createIcons(); + } + } + + + private setupEventListeners(): void { + // Editor input + this.editor?.addEventListener('input', () => { + this.updatePreview(); + }); + + // Sync scroll + const syncScrollBtn = document.getElementById('mdSyncScroll'); + syncScrollBtn?.addEventListener('click', () => { + this.syncScroll = !this.syncScroll; + syncScrollBtn.classList.toggle('md-editor-btn-primary'); + syncScrollBtn.classList.toggle('md-editor-btn-secondary'); + }); + + // Editor scroll sync + this.editor?.addEventListener('scroll', () => { + if (this.syncScroll && !this.isSyncing && this.editor && this.preview) { + this.isSyncing = true; + const scrollPercentage = this.editor.scrollTop / (this.editor.scrollHeight - this.editor.clientHeight); + this.preview.scrollTop = scrollPercentage * (this.preview.scrollHeight - this.preview.clientHeight); + setTimeout(() => this.isSyncing = false, 10); + } + }); + + // Preview scroll sync (bidirectional) + this.preview?.addEventListener('scroll', () => { + if (this.syncScroll && !this.isSyncing && this.editor && this.preview) { + this.isSyncing = true; + const scrollPercentage = this.preview.scrollTop / (this.preview.scrollHeight - this.preview.clientHeight); + this.editor.scrollTop = scrollPercentage * (this.editor.scrollHeight - this.editor.clientHeight); + setTimeout(() => this.isSyncing = false, 10); + } + }); + + // Theme toggle + const themeToggle = document.getElementById('themeToggle'); + const editorContainer = document.querySelector('.md-editor'); + themeToggle?.addEventListener('click', () => { + editorContainer?.classList.toggle('light-mode'); + themeToggle.classList.toggle('active'); + }); + + // Settings modal open + document.getElementById('mdSettings')?.addEventListener('click', () => { + const modal = document.getElementById('mdSettingsModal'); + if (modal) { + modal.style.display = 'flex'; + } + }); + + // Settings modal close + document.getElementById('mdCloseSettings')?.addEventListener('click', () => { + const modal = document.getElementById('mdSettingsModal'); + if (modal) { + modal.style.display = 'none'; + } + }); + + // Close modal on overlay click + document.getElementById('mdSettingsModal')?.addEventListener('click', (e) => { + if ((e.target as HTMLElement).classList.contains('md-editor-modal-overlay')) { + const modal = document.getElementById('mdSettingsModal'); + if (modal) { + modal.style.display = 'none'; + } + } + }); + + // Settings checkboxes + document.getElementById('mdOptHtml')?.addEventListener('change', (e) => { + this.mdOptions.html = (e.target as HTMLInputElement).checked; + this.updateMarkdownIt(); + }); + + document.getElementById('mdOptBreaks')?.addEventListener('change', (e) => { + this.mdOptions.breaks = (e.target as HTMLInputElement).checked; + this.updateMarkdownIt(); + }); + + document.getElementById('mdOptLinkify')?.addEventListener('change', (e) => { + this.mdOptions.linkify = (e.target as HTMLInputElement).checked; + this.updateMarkdownIt(); + }); + + document.getElementById('mdOptTypographer')?.addEventListener('change', (e) => { + this.mdOptions.typographer = (e.target as HTMLInputElement).checked; + this.updateMarkdownIt(); + }); + + // Preset selector + document.getElementById('mdPreset')?.addEventListener('change', (e) => { + const preset = (e.target as HTMLSelectElement).value; + this.applyPreset(preset as 'default' | 'commonmark' | 'zero'); + }); + + // Upload button + document.getElementById('mdUpload')?.addEventListener('click', () => { + document.getElementById('mdFileInput')?.click(); + }); + + // File input change + document.getElementById('mdFileInput')?.addEventListener('change', (e) => { + const file = (e.target as HTMLInputElement).files?.[0]; + if (file) { + this.loadFile(file); + } + }); + + // Export PDF + document.getElementById('mdExport')?.addEventListener('click', () => { + this.exportPdf(); + }); + + // Keyboard shortcuts + this.editor?.addEventListener('keydown', (e) => { + // Ctrl/Cmd + S to export + if ((e.ctrlKey || e.metaKey) && e.key === 's') { + e.preventDefault(); + this.exportPdf(); + } + // Tab key for indentation + if (e.key === 'Tab') { + e.preventDefault(); + const start = this.editor!.selectionStart; + const end = this.editor!.selectionEnd; + const value = this.editor!.value; + this.editor!.value = value.substring(0, start) + ' ' + value.substring(end); + this.editor!.selectionStart = this.editor!.selectionEnd = start + 2; + this.updatePreview(); + } + }); + } + + private currentPreset: 'default' | 'commonmark' | 'zero' = 'default'; + + private applyPreset(preset: 'default' | 'commonmark' | 'zero'): void { + this.currentPreset = preset; + + // Update options based on preset + if (preset === 'commonmark') { + this.mdOptions = { html: false, breaks: false, linkify: false, typographer: false }; + } else if (preset === 'zero') { + this.mdOptions = { html: false, breaks: false, linkify: false, typographer: false }; + } else { + this.mdOptions = { html: true, breaks: false, linkify: true, typographer: true }; + } + + // Update UI checkboxes + (document.getElementById('mdOptHtml') as HTMLInputElement).checked = this.mdOptions.html; + (document.getElementById('mdOptBreaks') as HTMLInputElement).checked = this.mdOptions.breaks; + (document.getElementById('mdOptLinkify') as HTMLInputElement).checked = this.mdOptions.linkify; + (document.getElementById('mdOptTypographer') as HTMLInputElement).checked = this.mdOptions.typographer; + + this.updateMarkdownIt(); + } + + private async loadFile(file: File): Promise { + try { + const text = await file.text(); + this.setContent(text); + } catch (error) { + console.error('Failed to load file:', error); + } + } + + + private createMarkdownIt(): MarkdownIt { + // Use preset if commonmark or zero + let md: MarkdownIt; + if (this.currentPreset === 'commonmark') { + md = new MarkdownIt('commonmark'); + } else if (this.currentPreset === 'zero') { + md = new MarkdownIt('zero'); + // Enable basic features for zero preset + md.enable(['paragraph', 'newline', 'text']); + } else { + md = new MarkdownIt({ + ...this.mdOptions, + highlight: (str: string, lang: string) => { + if (lang && hljs.getLanguage(lang)) { + try { + return hljs.highlight(str, { language: lang, ignoreIllegals: true }).value; + } catch { + // Fall through to default + } + } + return ''; // Use external default escaping + } + }); + } + + // Apply plugins only for default preset (plugins may not work well with commonmark/zero) + if (this.currentPreset === 'default') { + md.use(sub) // Subscript: ~text~ -> text + .use(sup) // Superscript: ^text^ -> text + .use(footnote) // Footnotes: [^1] and [^1]: footnote text + .use(deflist) // Definition lists + .use(abbr) // Abbreviations: *[abbr]: full text + .use(emoji) // Emoji: :smile: -> 😄 + .use(ins) // Inserted text: ++text++ -> text + .use(mark) // Marked text: ==text== -> text + .use(taskLists, { enabled: true, label: true, labelAfter: true }) // Task lists: - [x] done + .use(anchor, { permalink: false }) // Header anchors + .use(tocDoneRight); // Table of contents: ${toc} + } + + return md; + } + + private updateMarkdownIt(): void { + this.md = this.createMarkdownIt(); + this.configureLinkRenderer(); + this.updatePreview(); + } + + private updatePreview(): void { + if (!this.editor || !this.preview) return; + + const markdown = this.editor.value; + const html = this.md.render(markdown); + this.preview.innerHTML = html; + this.renderMermaidDiagrams(); + } + + private async renderMermaidDiagrams(): Promise { + if (!this.preview) return; + + const mermaidBlocks = this.preview.querySelectorAll('pre > code.language-mermaid'); + + for (let i = 0; i < mermaidBlocks.length; i++) { + const block = mermaidBlocks[i] as HTMLElement; + const code = block.textContent || ''; + const pre = block.parentElement; + + if (pre && code.trim()) { + try { + const id = `mermaid-diagram-${i}-${Date.now()}`; + const { svg } = await mermaid.render(id, code.trim()); + + const wrapper = document.createElement('div'); + wrapper.className = 'mermaid-diagram'; + wrapper.innerHTML = svg; + + pre.replaceWith(wrapper); + } catch (error) { + console.error('Mermaid rendering error:', error); + const errorDiv = document.createElement('div'); + errorDiv.className = 'mermaid-error'; + errorDiv.textContent = `Mermaid Error: ${(error as Error).message}`; + pre.replaceWith(errorDiv); + } + } + } + } + + public setContent(content: string): void { + if (this.editor) { + this.editor.value = content; + this.updatePreview(); + } + } + + public getContent(): string { + return this.editor?.value || ''; + } + + public getHtml(): string { + return this.md.render(this.getContent()); + } + + private exportPdf(): void { + // Use browser's native print functionality + window.print(); + } + + private getStyledHtml(): string { + const content = this.getHtml(); + + return ` + + + + + + +${content} + +`; + } + + private applyI18n(): void { + // Apply translations to elements within this component + applyTranslations(); + + // Special handling for select options (data-i18n on options doesn't work with applyTranslations) + const presetSelect = document.getElementById('mdPreset') as HTMLSelectElement; + if (presetSelect) { + const options = presetSelect.querySelectorAll('option[data-i18n]'); + options.forEach((option) => { + const key = option.getAttribute('data-i18n'); + if (key) { + // Use i18next directly for option text + const translated = (window as any).i18next?.t(key); + if (translated && translated !== key) { + option.textContent = translated; + } + } + }); + } + } + + public destroy(): void { + this.container.innerHTML = ''; + } +} diff --git a/src/js/utils/simple-mode-footer.ts b/src/js/utils/simple-mode-footer.ts index f2a1658..7d9ba50 100644 --- a/src/js/utils/simple-mode-footer.ts +++ b/src/js/utils/simple-mode-footer.ts @@ -1,45 +1,38 @@ import { APP_VERSION } from '../../version.js'; import { createLanguageSwitcher } from '../i18n/language-switcher.js'; -// Handle simple mode footer replacement for tool pages +// Handle simple mode adjustments for tool pages if (__SIMPLE_MODE__) { - const footer = document.querySelector('footer'); - if (footer && !document.querySelector('[data-simple-footer]')) { - footer.style.display = 'none'; + const sectionsToHide = [ + 'How It Works', + 'Related PDF Tools', + 'Related Tools', + 'Frequently Asked Questions', + ]; - const simpleFooter = document.createElement('footer'); - simpleFooter.className = 'mt-16 border-t-2 border-gray-700 py-8'; - simpleFooter.setAttribute('data-simple-footer', 'true'); - simpleFooter.innerHTML = ` -
-
-
-
- Bento PDF Logo - BentoPDF -
-

- © 2025 BentoPDF. All rights reserved. -

-

- Version ${APP_VERSION} -

-
-
-
-
- `; - document.body.appendChild(simpleFooter); - - const langContainer = simpleFooter.querySelector('#simple-mode-lang-switcher'); - if (langContainer) { - const switcher = createLanguageSwitcher(); - const dropdown = switcher.querySelector('div[role="menu"]'); - if (dropdown) { - dropdown.classList.remove('mt-2'); - dropdown.classList.add('bottom-full', 'mb-2'); + document.querySelectorAll('section').forEach((section) => { + const h2 = section.querySelector('h2'); + if (h2) { + const heading = h2.textContent?.trim() || ''; + if (sectionsToHide.some((text) => heading.includes(text))) { + (section as HTMLElement).style.display = 'none'; } - langContainer.appendChild(switcher); } + }); + + const versionElement = document.getElementById('app-version-simple'); + if (versionElement) { + versionElement.textContent = APP_VERSION; + } + + const langContainer = document.getElementById('simple-mode-lang-switcher'); + if (langContainer) { + const switcher = createLanguageSwitcher(); + const dropdown = switcher.querySelector('div[role="menu"]'); + if (dropdown) { + dropdown.classList.remove('mt-2'); + dropdown.classList.add('bottom-full', 'mb-2'); + } + langContainer.appendChild(switcher); } } diff --git a/src/js/utils/wasm-preloader.ts b/src/js/utils/wasm-preloader.ts new file mode 100644 index 0000000..bf909a6 --- /dev/null +++ b/src/js/utils/wasm-preloader.ts @@ -0,0 +1,132 @@ +import { getLibreOfficeConverter } from './libreoffice-loader.js'; +import { PyMuPDF } from '@bentopdf/pymupdf-wasm'; +import loadGsWASM from '@bentopdf/gs-wasm'; +import { setCachedGsModule } from './ghostscript-loader.js'; +import { getWasmBaseUrl } from '../config/wasm-cdn-config.js'; + +export enum PreloadStatus { + IDLE = 'idle', + LOADING = 'loading', + READY = 'ready', + ERROR = 'error' +} + +interface PreloadState { + libreoffice: PreloadStatus; + pymupdf: PreloadStatus; + ghostscript: PreloadStatus; +} + +const preloadState: PreloadState = { + libreoffice: PreloadStatus.IDLE, + pymupdf: PreloadStatus.IDLE, + ghostscript: PreloadStatus.IDLE +}; + +let pymupdfInstance: PyMuPDF | null = null; + +export function getPreloadStatus(): Readonly { + return { ...preloadState }; +} + +export function getPymupdfInstance(): PyMuPDF | null { + return pymupdfInstance; +} + +async function preloadLibreOffice(): Promise { + if (preloadState.libreoffice !== PreloadStatus.IDLE) return; + + preloadState.libreoffice = PreloadStatus.LOADING; + console.log('[Preloader] Starting LibreOffice WASM preload...'); + + try { + const converter = getLibreOfficeConverter(); + await converter.initialize(); + preloadState.libreoffice = PreloadStatus.READY; + console.log('[Preloader] LibreOffice WASM ready'); + } catch (e) { + preloadState.libreoffice = PreloadStatus.ERROR; + console.warn('[Preloader] LibreOffice preload failed:', e); + } +} + +async function preloadPyMuPDF(): Promise { + if (preloadState.pymupdf !== PreloadStatus.IDLE) return; + + preloadState.pymupdf = PreloadStatus.LOADING; + console.log('[Preloader] Starting PyMuPDF preload...'); + + try { + const pymupdfBaseUrl = getWasmBaseUrl('pymupdf'); + pymupdfInstance = new PyMuPDF(pymupdfBaseUrl); + await pymupdfInstance.load(); + preloadState.pymupdf = PreloadStatus.READY; + console.log('[Preloader] PyMuPDF ready'); + } catch (e) { + preloadState.pymupdf = PreloadStatus.ERROR; + console.warn('[Preloader] PyMuPDF preload failed:', e); + } +} + +async function preloadGhostscript(): Promise { + if (preloadState.ghostscript !== PreloadStatus.IDLE) return; + + preloadState.ghostscript = PreloadStatus.LOADING; + console.log('[Preloader] Starting Ghostscript WASM preload...'); + + try { + const gsBaseUrl = getWasmBaseUrl('ghostscript'); + const gsModule = await loadGsWASM({ + locateFile: (path: string) => { + if (path.endsWith('.wasm')) { + return gsBaseUrl + 'gs.wasm'; + } + return path; + }, + print: () => { }, + printErr: () => { }, + }); + setCachedGsModule(gsModule as any); + preloadState.ghostscript = PreloadStatus.READY; + console.log('[Preloader] Ghostscript WASM ready'); + } catch (e) { + preloadState.ghostscript = PreloadStatus.ERROR; + console.warn('[Preloader] Ghostscript preload failed:', e); + } +} + +function scheduleIdleTask(task: () => Promise): void { + if ('requestIdleCallback' in window) { + requestIdleCallback(() => task(), { timeout: 5000 }); + } else { + setTimeout(() => task(), 1000); + } +} + +export function startBackgroundPreload(): void { + console.log('[Preloader] Scheduling background WASM preloads...'); + + const libreOfficePages = [ + 'word-to-pdf', 'excel-to-pdf', 'ppt-to-pdf', 'powerpoint-to-pdf', + 'docx-to-pdf', 'xlsx-to-pdf', 'pptx-to-pdf', 'csv-to-pdf', + 'rtf-to-pdf', 'odt-to-pdf', 'ods-to-pdf', 'odp-to-pdf' + ]; + + const currentPath = window.location.pathname; + const isLibreOfficePage = libreOfficePages.some(page => currentPath.includes(page)); + + if (isLibreOfficePage) { + console.log('[Preloader] Skipping preloads on LibreOffice page to save memory'); + return; + } + + scheduleIdleTask(async () => { + console.log('[Preloader] Starting sequential WASM preloads...'); + + await preloadPyMuPDF(); + await preloadGhostscript(); + + console.log('[Preloader] Sequential preloads complete (LibreOffice skipped - loaded on demand)'); + }); +} + diff --git a/src/js/utils/xml-to-pdf.ts b/src/js/utils/xml-to-pdf.ts new file mode 100644 index 0000000..506b443 --- /dev/null +++ b/src/js/utils/xml-to-pdf.ts @@ -0,0 +1,196 @@ +import { jsPDF } from 'jspdf'; +import autoTable from 'jspdf-autotable'; + +export interface XmlToPdfOptions { + onProgress?: (percent: number, message: string) => void; +} + +interface jsPDFWithAutoTable extends jsPDF { + lastAutoTable?: { finalY: number }; +} + +export async function convertXmlToPdf( + file: File, + options?: XmlToPdfOptions +): Promise { + const { onProgress } = options || {}; + + onProgress?.(10, 'Reading XML file...'); + const xmlText = await file.text(); + + onProgress?.(30, 'Parsing XML structure...'); + const parser = new DOMParser(); + const xmlDoc = parser.parseFromString(xmlText, 'text/xml'); + + const parseError = xmlDoc.querySelector('parsererror'); + if (parseError) { + throw new Error('Invalid XML: ' + parseError.textContent); + } + + onProgress?.(50, 'Analyzing data structure...'); + + const doc: jsPDFWithAutoTable = new jsPDF({ + orientation: 'landscape', + unit: 'mm', + format: 'a4' + }); + + const pageWidth = doc.internal.pageSize.getWidth(); + let yPosition = 20; + + const root = xmlDoc.documentElement; + const rootName = formatTitle(root.tagName); + + doc.setFontSize(18); + doc.setFont('helvetica', 'bold'); + doc.text(rootName, pageWidth / 2, yPosition, { align: 'center' }); + yPosition += 15; + + onProgress?.(60, 'Generating formatted content...'); + + const children = Array.from(root.children); + + if (children.length > 0) { + const groups = groupByTagName(children); + + for (const [groupName, elements] of Object.entries(groups)) { + const { headers, rows } = extractTableData(elements); + + if (headers.length > 0 && rows.length > 0) { + if (Object.keys(groups).length > 1) { + doc.setFontSize(14); + doc.setFont('helvetica', 'bold'); + doc.text(formatTitle(groupName), 14, yPosition); + yPosition += 8; + } + + autoTable(doc, { + head: [headers.map(h => formatTitle(h))], + body: rows, + startY: yPosition, + styles: { + fontSize: 9, + cellPadding: 4, + overflow: 'linebreak', + }, + headStyles: { + fillColor: [79, 70, 229], + textColor: 255, + fontStyle: 'bold', + }, + alternateRowStyles: { + fillColor: [243, 244, 246], + }, + margin: { top: 20, left: 14, right: 14 }, + theme: 'striped', + didDrawPage: (data) => { + yPosition = (data.cursor?.y || yPosition) + 10; + } + }); + + yPosition = (doc.lastAutoTable?.finalY || yPosition) + 15; + } + } + } else { + const kvPairs = extractKeyValuePairs(root); + if (kvPairs.length > 0) { + autoTable(doc, { + head: [['Property', 'Value']], + body: kvPairs, + startY: yPosition, + styles: { + fontSize: 10, + cellPadding: 5, + }, + headStyles: { + fillColor: [79, 70, 229], + textColor: 255, + fontStyle: 'bold', + }, + columnStyles: { + 0: { fontStyle: 'bold', cellWidth: 60 }, + 1: { cellWidth: 'auto' }, + }, + margin: { left: 14, right: 14 }, + theme: 'striped', + }); + } + } + + onProgress?.(90, 'Finalizing PDF...'); + + const pdfBlob = doc.output('blob'); + + onProgress?.(100, 'Complete!'); + return pdfBlob; +} + + +function groupByTagName(elements: Element[]): Record { + const groups: Record = {}; + + for (const element of elements) { + const tagName = element.tagName; + if (!groups[tagName]) { + groups[tagName] = []; + } + groups[tagName].push(element); + } + + return groups; +} + +function extractTableData(elements: Element[]): { headers: string[], rows: string[][] } { + if (elements.length === 0) { + return { headers: [], rows: [] }; + } + + const headerSet = new Set(); + for (const element of elements) { + for (const child of Array.from(element.children)) { + headerSet.add(child.tagName); + } + } + const headers = Array.from(headerSet); + + const rows: string[][] = []; + for (const element of elements) { + const row: string[] = []; + for (const header of headers) { + const child = element.querySelector(header); + row.push(child?.textContent?.trim() || ''); + } + rows.push(row); + } + + return { headers, rows }; +} + + +function extractKeyValuePairs(element: Element): string[][] { + const pairs: string[][] = []; + + for (const child of Array.from(element.children)) { + const key = child.tagName; + const value = child.textContent?.trim() || ''; + if (value) { + pairs.push([formatTitle(key), value]); + } + } + + for (const attr of Array.from(element.attributes)) { + pairs.push([formatTitle(attr.name), attr.value]); + } + + return pairs; +} + + +function formatTitle(tagName: string): string { + return tagName + .replace(/[_-]/g, ' ') + .replace(/([a-z])([A-Z])/g, '$1 $2') + .split(' ') + .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(' '); +} diff --git a/src/pages/add-attachments.html b/src/pages/add-attachments.html index 35305d2..a0ffbf5 100644 --- a/src/pages/add-attachments.html +++ b/src/pages/add-attachments.html @@ -1,228 +1,426 @@ - - + + + + Add Attachments Online Free - Add Attachments Tool | BentoPDF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Add Attachments to PDF - BentoPDF - - - - - - - - - + + - - - + + -
-
- + + + + + + + -

Add Attachments to PDF -

-

- Upload a PDF, then add files to embed as attachments. + + {{> navbar }} + +

+
+ + +

+ Add Attachments Free Online - Fast & Secure +

+

+ Upload a PDF, then add files to embed as attachments. +

+ + +
+
+ +

+ Click to select PDF + or drag and drop

- - -
-
- -

Click to select PDF or drag and drop

-

Your files never leave your - device.

-
- -
- -
- - - +

+ Your files never leave your device. +

+
+
+ +
+ + + +
-