diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..258cc99 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,19 @@ +FROM mcr.microsoft.com/devcontainers/base:focal + +RUN apt update && apt upgrade -y + +RUN apt install -y software-properties-common apt-transport-https ca-certificates curl gnupg + +RUN mkdir -p /etc/apt/keyrings +RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg + +RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list +RUN apt update && apt install -y nodejs + +RUN corepack enable + +RUN echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list +RUN curl -fSsL https://dl.google.com/linux/linux_signing_key.pub | sudo gpg --dearmor | sudo tee /usr/share/keyrings/google-chrome.gpg >> /dev/null +RUN echo deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main | sudo tee /etc/apt/sources.list.d/google-chrome.list + +RUN apt update && apt install -y google-chrome-stable firefox diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..e89dbc7 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,26 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node +{ + "name": "TabsAsideExtension", + "build": { + "dockerfile": "Dockerfile" + }, + + // Configure tool-specific properties. + "customizations": { + "vscode": { + "extensions": [ + "dbaeumer.vscode-eslint", + "zardoy.disable-ts-errors", + "github.vscode-github-actions", + "GitHub.vscode-pull-request-github", + "bierner.github-markdown-preview", + "mrmlnc.vscode-scss", + "Gruntfuggly.todo-tree", + "redhat.vscode-yaml" + ] + } + }, + + "postCreateCommand": "yarn install" +} diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..62570b8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,107 @@ +name: "🐞 Bug Report" +description: Create a report to help us improve the extension +title: "[Bug]: " +labels: ["bug", "needs-triage"] +assignees: + - xfox111 +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + + - type: textarea + id: desc + attributes: + label: Description + description: A clear and concise description of what the bug is. + placeholder: e.g. Sometimes when generating a password not all character sets are included + validations: + required: true + + - type: textarea + attributes: + label: Reproduction steps + description: Precisely describe minimal number of steps that make the bug to appear + placeholder: | + 1. Go to '...' + 2. Click on '...' + 3. Scroll down to '...' + 4. See '...' + validations: + required: true + + - type: textarea + attributes: + label: Expected behavior + description: A clear and concise description of what you expected to happen. + placeholder: e.g. Generated password should include at least one character from every enabled character set + validations: + required: true + + - type: textarea + attributes: + label: Screenshot + description: If applicable, add screenshots to help explain your problem. + validations: + required: false + + - type: dropdown + id: os + attributes: + label: Operating system + options: + - "Windows 10 and newer" + - "Windows 8/8.1" + - "Windows 7 and older" + - "MacOS" + - "Debian or Debian-based" + - "Other" + validations: + required: true + + - type: input + id: browser + attributes: + label: Browser name and version + placeholder: e.g. Microsoft Edge 119.0.2151.58 + description: Put here your browser's name and version + validations: + required: true + + - type: input + id: version + attributes: + label: Extension version + placeholder: e.g. 3.0.0 + validations: + required: true + + - type: textarea + id: context + attributes: + label: Additional context + description: Add any other context about the problem here. + validations: + required: false + + - type: dropdown + id: requested-help + attributes: + label: Are you willing to submit a PR for this issue? + options: + - "yes" + - "no" + validations: + required: true + + - type: checkboxes + id: checkboxes + attributes: + label: Validations + description: Before submitting the issue, please make sure you do the following + options: + - label: Check that there isn't already an issue that reports the same bug to avoid creating a duplicate. + required: true + - label: The provided reproduction is a minimal reproducible example of the bug. + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..7a1fa3b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,7 @@ +# yaml-language-server: $schema=https://json.schemastore.org/github-issue-config.json + +blank_issues_enabled: true +contact_links: + - name: Questions & Discussions + url: https://github.com/XFox111/TabsAsideExtension/discussions + about: Use GitHub discussions for message-board style questions and discussions. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..6318208 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,62 @@ +name: "🚀 New feature proposal" +description: Suggest a feature idea for this project +title: "[Feature]: " +labels: ["feature", "needs-triage"] +assignees: + - xfox111 +body: + - type: markdown + attributes: + value: | + Thanks for your interest in the project and taking the time to fill out this feature report! + + - type: textarea + id: proposition + attributes: + label: Proposed solution + description: Describe the solution you'd like + validations: + required: true + + - type: textarea + id: justification + attributes: + label: Justification + description: Is your feature request related to a problem? Please describe. + validations: + required: true + + - type: textarea + id: alts + attributes: + label: Alternatives + description: Describe alternatives you've considered. + validations: + required: true + + - type: textarea + id: context + attributes: + label: Additional context + description: Add any other context or screenshots about the feature request here. + validations: + required: false + + - type: dropdown + id: requested-help + attributes: + label: Are you willing to submit a PR for this issue? + options: + - "yes" + - "no" + validations: + required: true + + - type: checkboxes + id: checkboxes + attributes: + label: Validations + description: Before submitting the issue, please make sure you do the following + options: + - label: Check that there isn't already an issue that request the same feature to avoid creating a duplicate. + required: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..cf4e028 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,45 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +# yaml-language-server: $schema=https://json.schemastore.org/dependabot-2.0.json + +version: 2 +updates: + + - package-ecosystem: "npm" # See documentation for possible values + directory: "/" # Location of package manifests + target-branch: "next" + assignees: + - "xfox111" + reviewers: + - "xfox111" + schedule: + interval: monthly + rebase-strategy: disabled + open-pull-requests-limit: 20 + + - package-ecosystem: "github-actions" + directory: "/" + target-branch: "next" + assignees: + - "xfox111" + reviewers: + - "xfox111" + schedule: + interval: monthly + rebase-strategy: disabled + open-pull-requests-limit: 20 + + - package-ecosystem: "devcontainers" + directory: "/" + target-branch: "next" + assignees: + - "xfox111" + reviewers: + - "xfox111" + schedule: + interval: monthly + rebase-strategy: disabled + open-pull-requests-limit: 20 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..a0a4001 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,33 @@ + + +## Description + + +Resolves: #issue_number + + + + + + + diff --git a/.github/release_description_template.md b/.github/release_description_template.md new file mode 100644 index 0000000..812c9ce --- /dev/null +++ b/.github/release_description_template.md @@ -0,0 +1,14 @@ + + +## What's new + + + + +Refer to [Download section of the README.md](https://github.com/XFox111/TabsAsideExtension#download) for sideloading instructions and download links diff --git a/.github/workflows/cd_pipeline.yml b/.github/workflows/cd_pipeline.yml new file mode 100644 index 0000000..db0f4b1 --- /dev/null +++ b/.github/workflows/cd_pipeline.yml @@ -0,0 +1,144 @@ +name: Release pipeline + +on: + release: + types: [ released ] + workflow_dispatch: + inputs: + bypass_audit: + description: Bypass npm audit + type: boolean + default: false + targets: + description: Targets + required: true + default: '["chrome","firefox"]' + type: choice + options: + - '["chrome","firefox"]' + - '["chrome"]' + - '["firefox"]' + firefox: + description: Deploy Firefox + type: boolean + default: true + chrome: + description: Deploy Chrome + type: boolean + default: true + edge: + description: Deploy Edge + type: boolean + default: true + gh-release: + description: Attach to GitHub release + type: boolean + default: true + +jobs: + build: + runs-on: ubuntu-latest + container: node:20 + strategy: + fail-fast: false + matrix: + target: ${{ fromJSON(github.event.inputs.targets || '["chrome","firefox"]') }} + + steps: + - uses: actions/checkout@main + + - run: yarn install + - run: yarn zip -b ${{ matrix.target }} + + - name: Drop build artifacts (${{ matrix.target }}) + uses: actions/upload-artifact@main + with: + name: ${{ matrix.target }} + path: ./.output/tabs-aside-*-${{ matrix.target }}.zip + include-hidden-files: true + + - name: web-ext lint + if: ${{ matrix.target == 'firefox' }} + uses: freaktechnik/web-ext-lint@main + with: + extension-root: ./.output/firefox-mv3 + self-hosted: false + + - run: yarn audit + if: ${{ github.event_name == 'release' || github.event.inputs.bypass_audit == 'false' }} + + publish-github: + needs: build + if: ${{ github.event_name == 'release' || github.event.inputs.gh-release == 'true' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + target: ${{ fromJSON(github.event.inputs.targets || '["chrome","firefox"]') }} + + steps: + - uses: actions/download-artifact@main + with: + name: ${{ matrix.target }} + + - name: Attach build to release + uses: xresloader/upload-to-github-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + file: tabs-aside-*-${{ matrix.target }}.zip + draft: false + overwrite: true + update_latest_release: true + + publish-chrome: + needs: build + if: ${{ github.event_name == 'release' || (github.event.inputs.chrome == 'true' && contains(github.event.inputs.targets, 'chrome')) }} + runs-on: ubuntu-latest + + steps: + - uses: actions/download-artifact@main + with: + name: chrome + + - uses: wdzeng/chrome-extension@v1.3.0 + with: + extension-id: mgmjbodjgijnebfgohlnjkegdpbdjgin + zip-path: tabs-aside-*-chrome.zip + client-id: ${{ secrets.CHROME_CLIENT_ID }} + client-secret: ${{ secrets.CHROME_CLIENT_SECRET }} + refresh-token: ${{ secrets.CHROME_REFRESH_TOKEN }} + + publish-edge: + needs: build + if: ${{ github.event_name == 'release' || (github.event.inputs.edge == 'true' && contains(github.event.inputs.targets, 'chrome')) }} + runs-on: ubuntu-latest + + steps: + - uses: actions/download-artifact@main + with: + name: chrome + + - uses: wdzeng/edge-addon@v2.1.0 + with: + product-id: ${{ secrets.EDGE_PRODUCT_ID }} + zip-path: tabs-aside-*-chrome.zip + client-id: ${{ secrets.EDGE_CLIENT_ID }} + api-key: ${{ secrets.EDGE_API_KEY }} + + publish-firefox: + needs: build + if: ${{ github.event_name == 'release' || (github.event.inputs.firefox == 'true' && contains(github.event.inputs.targets, 'firefox')) }} + runs-on: ubuntu-latest + + steps: + - uses: actions/download-artifact@main + with: + name: firefox + + - uses: wdzeng/firefox-addon@v1.1.2 + with: + addon-guid: ${{ secrets.FIREFOX_EXT_UUID }} + xpi-path: tabs-aside-*-firefox.zip + jwt-issuer: ${{ secrets.FIREFOX_API_KEY }} + jwt-secret: ${{ secrets.FIREFOX_CLIENT_SECRET }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..782a458 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,86 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "main", "next" ] + paths-ignore: + - '**.md' + - 'LICENSE' + - '**/cd_pipeline.yaml' + - '**/dependabot.yml' + - '**/pr_pipeline.yaml' + - '.vscode/*' + pull_request: + # The branches below must be a subset of the branches above + branches: [ "main", "next" ] + paths-ignore: + - '**.md' + - 'LICENSE' + - '**/cd_pipeline.yaml' + - '**/dependabot.yml' + - '**/pr_pipeline.yaml' + - '.vscode/*' + schedule: + - cron: '24 7 * * 3' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'typescript' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/pr_next.yml b/.github/workflows/pr_next.yml new file mode 100644 index 0000000..7a30dc6 --- /dev/null +++ b/.github/workflows/pr_next.yml @@ -0,0 +1,31 @@ +name: PR next workflow + +on: + push: + branches: [ main ] + paths: + - 'package.json' + workflow_dispatch: + +permissions: + contents: write + +jobs: + create-release-draft: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + + - name: Get version from package.json + id: get_version + run: | + extver=`jq -r ".version" package.json` + echo "version=$extver" >> "$GITHUB_OUTPUT" + + - uses: dev-build-deploy/release-me@v0.18.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + prefix: v + draft: true + version: v${{ steps.get_version.outputs.version }} + release-notes: .github/release_description_template.md diff --git a/.github/workflows/pr_pipeline.yml b/.github/workflows/pr_pipeline.yml new file mode 100644 index 0000000..5b2c872 --- /dev/null +++ b/.github/workflows/pr_pipeline.yml @@ -0,0 +1,57 @@ +name: PR check pipeline + +on: + pull_request: + branches: [ "main", "next" ] + paths-ignore: + - '**.md' + - 'LICENSE' + - 'PRIVACY' + - '**/cd_pipeline.yaml' + - '**/dependabot.yml' + - '**/codeql-analysis.yml' + - '**/pr_next.yaml' + - '.vscode/*' + - '.devcontainer/*' + workflow_dispatch: + inputs: + targets: + description: Targets + required: true + default: '["chrome","firefox"]' + type: choice + options: + - '["chrome","firefox"]' + - '["chrome"]' + - '["firefox"]' + +jobs: + build: + runs-on: ubuntu-latest + container: node:23 + strategy: + fail-fast: false + matrix: + target: ${{ fromJSON(github.event.inputs.targets || '["chrome","firefox"]') }} + + steps: + - uses: actions/checkout@main + + - run: yarn install + - run: yarn zip -b ${{ matrix.target }} + + - name: Drop artifacts (${{ matrix.target }}) + uses: actions/upload-artifact@main + with: + name: ${{ matrix.target }} + path: ./.output/tabs-aside-*-${{ matrix.target }}.zip + include-hidden-files: true + + - name: web-ext lint + if: ${{ matrix.target == 'firefox' }} + uses: freaktechnik/web-ext-lint@main + with: + extension-root: ./.output/firefox-mv3 + self-hosted: false + + - run: yarn audit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a256953 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.output +stats.html +stats-*.json +.wxt +web-ext.config.ts + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..8632321 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,12 @@ +{ + "recommendations": [ + "bierner.github-markdown-preview", + "dbaeumer.vscode-eslint", + "github.vscode-github-actions", + "Gruntfuggly.todo-tree", + "jock.svg", + "ms-azuretools.vscode-docker", + "saeris.markdown-github-alerts", + "zardoy.disable-ts-errors" + ] +} diff --git a/App.tsx b/App.tsx new file mode 100644 index 0000000..1db5711 --- /dev/null +++ b/App.tsx @@ -0,0 +1,11 @@ +import DialogProvider from "@/contexts/DialogProvider"; +import ThemeProvider from "@/contexts/ThemeProvider"; + +const App: React.FC = ({ children }: React.PropsWithChildren) => + + + { children } + + ; + +export default App; diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..ad52cd6 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,134 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[opensource@xfox111.net](mailto:opensource@xfox111.net). +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +> Contributor Covenant is released under the [Creative Commons Attribution 4.0 International Public License](https://github.com/EthicalSource/contributor_covenant/blob/release/LICENSE.md). + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..60a9362 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,4 @@ +# Contribution Guidelines + +> [!IMPORTANT] +> This article has been moved to the [project's Wiki section](https://github.com/XFox111/TabsAsideExtension/wiki/Contribution-Guidelines) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..db0177c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Eugene Fox + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/PRIVACY.md b/PRIVACY.md new file mode 100644 index 0000000..dd4cbf0 --- /dev/null +++ b/PRIVACY.md @@ -0,0 +1,8 @@ +# Tabs aside extension Privacy policy +1. Developers of the extension don't affiliate with Google LLC, Mozilla Foundation or Microsoft Corporation in any way. +2. This extension only stores user data related to its core functionality. This includes: + - User settings + - User saved collections of tabs +2. This extension doesn't use any tracking software, nor does it collect, sell or share any personal data with any third parties. +3. This extension uses cloud storage built into your browser to store its data. +4. Refer to your browser's developer regarding the privacy policy of the cloud storage used by your browser. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f36d9b0 --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +[![GitHub release (latest by date)](https://img.shields.io/github/v/release/xfox111/TabsAsideExtension)](https://github.com/xfox111/TabsAsideExtension/releases/latest) +[![GitHub last commit](https://img.shields.io/github/last-commit/xfox111/TabsAsideExtension?label=Last+update)](https://github.com/XFox111/TabsAsideExtension/commits/main) + + + + + Password generator + + +Stemming its roots from the original Microsoft Edge browser feature, this extension has grown much bigger than just a temporary storage for tabs. + +It allows you to save and manage your tabs in a convenient way, providing a range of features that make it easy to organize and access your saved tabs. + +## Features +- **Save tabs**: Save all your open tabs in a single click, and restore them later +- **Organize tabs**: Create collections and subgroups to organize your saved tabs +- **Search tabs**: Quickly find the tabs you need using the search feature +- **Sync across devices**: Access your saved tabs from any device with your account +- **Go dark**: Dark mode support for a more comfortable browsing experience +- **Personalize**: Change the appearance and behavior of the extension to suit your needs + +Check out our [latest blog post](https://at.xfox111.net/tabs-aside-3-0) regarding all the new features and improvements in Tabs aside 3.0 + +## Languages +- Chinese (Simplified) +- English +- Italian +- Polish +- Portuguese (Brazil) +- Russian +- Spanish +- Ukrainian + +## Download +[![Chrome Web Store](https://img.shields.io/chrome-web-store/users/mgmjbodjgijnebfgohlnjkegdpbdjgin?label=Chrome%20Webstore%20downloads)](https://chrome.google.com/webstore/detail/mgmjbodjgijnebfgohlnjkegdpbdjgin) +[![Mozilla Add-on](https://img.shields.io/amo/users/ms-edge-tabs-aside?label=Firefox%20Webstore%20downloads)](https://addons.mozilla.org/firefox/addon/ms-edge-tabs-aside/) + +- [Google Chrome Webstore](https://chrome.google.com/webstore/detail/mgmjbodjgijnebfgohlnjkegdpbdjgin) +- [Microsoft Edge Add-ons Webstore](https://microsoftedge.microsoft.com/addons/detail/kmnblllmalkiapkfknnlpobmjjdnlhnd) +- [Firefox Add-ons](https://addons.mozilla.org/en-US/firefox/addon/ms-edge-tabs-aside/) +- [GitHub Releases](https://github.com/xfox111/TabsAsideExtension/releases/latest) + +### Sideloading (for testing purposes only) + +
+ Click to expand + +--- + +
+ Chromium-based browsers (Edge, Chrome, etc.) + +> 1. Go to [Releases](https://github.com/XFox111/TabsAsideExtension/releases) and select a release to download +> 2. Download attached archive for Chromium and unpack it +> 3. Go to `chrome://extensions` +> 4. Enable "Developer mode" +> 5. Click the "Load unpacked" button and navigate to the extension's root folder (contains `manifest.json`) +> 6. Done! + +
+ +
+ Firefox + +> 1. Go to [Releases](https://github.com/XFox111/TabsAsideExtension/releases) and select a release to download +> 2. Download attached archive for Firefox and unpack it +> 3. Go to `about:debugging#/runtime/this-firefox` +> 4. Click the "Load Temporary Add-on..." button and select `manifest.json` file in the root folder +> 5. Done! + +> **Important!** +This will _replace_ officialy installed version if you have one. +If you want to sideload it without replacing to run both versions at the same time - before loading add-on, open `manifest.json` in a text editor and change `id` key (it's `passwordgenerator@xfox111.net` by default) to something else + +
+ +> **Note:** If you delete the extension folder it will disappear from your browser +--- + +
+ +## Contributing +[![GitHub issues](https://img.shields.io/github/issues/xfox111/TabsAsideExtension)](https://github.com/xfox111/TabsAsideExtension/issues) +[![CI](https://github.com/XFox111/TabsAsideExtension/actions/workflows/cd_pipeline.yaml/badge.svg)](https://github.com/XFox111/TabsAsideExtension/actions/workflows/cd_pipeline.yaml) +[![GitHub repo size](https://img.shields.io/github/repo-size/xfox111/TabsAsideExtension?label=repo%20size)](https://github.com/xfox111/TabsAsideExtension) + +There are many ways in which you can participate in the project, for example: +- [Submit bugs and feature requests](https://github.com/xfox111/TabsAsideExtension/issues), and help us verify as they are checked in +- Review [source code changes](https://github.com/xfox111/TabsAsideExtension/pulls) +- Review documentation and make pull requests for anything from typos to new content + +If you are interested in fixing issues and contributing directly to the code base, please refer to the [Contribution Guidelines](https://github.com/XFox111/TabsAsideExtension/wiki/Contribution-Guidelines) + +--- + +[![Bluesky](https://img.shields.io/badge/%40xfox111.net-BSky?logo=bluesky&logoColor=%230285FF&label=Bluesky&labelColor=white&color=%230285FF)](https://bsky.app/profile/xfox111.net) +[![GitHub](https://img.shields.io/badge/%40xfox111-GitHub?logo=github&logoColor=%23181717&label=GitHub&labelColor=white&color=%23181717)](https://github.com/xfox111) +[![Buy Me a Coffee](https://img.shields.io/badge/%40xfox111-BMC?logo=buymeacoffee&logoColor=black&label=Buy%20me%20a%20coffee&labelColor=white&color=%23FFDD00)](https://buymeacoffee.com/xfox111) + +> Š2025 Eugene Fox. Licensed under [MIT license](https://github.com/XFox111/TabsAsideExtension/blob/main/LICENSE) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..5b2b0a1 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,11 @@ +# Security Policy + +## Supported Versions +Tabs aside extension has a linear versioning system. The latest version is always the most secure one. This is applied to major versions as well. If you are using an older version, please update it to the latest one. + +We regularly run security audits and fix any security issues that are found. If you find a security issue, please report it to us as described below. + +If you are willing to continue using an older version, you can sideload it from the [releases page](https://github.com/XFox111/TabsAsideExtension/releases). Use outdated versions at your own risk. + +## Reporting a Vulnerability +You can report a security issue by clicking "Report a vulnerability" button at the top-right of this page, or by going through [this link](https://github.com/XFox111/TabsAsideExtension/security/advisories/new) diff --git a/assets/BuyMeACoffee20.tsx b/assets/BuyMeACoffee20.tsx new file mode 100644 index 0000000..4c665c8 --- /dev/null +++ b/assets/BuyMeACoffee20.tsx @@ -0,0 +1,64 @@ +import { makeStyles } from "@fluentui/react-components"; +import { FluentIcon } from "@fluentui/react-icons"; + +export const BuyMeACoffee20Regular: FluentIcon = (props) => +{ + const cls = useStyles(); + return ( + + + + + + + + + + + + + + + + + + ); +}; + +export const BuyMeACoffee20Filled: FluentIcon = (props) => +{ + const cls = useStyles(); + return ( + + + + + + + + + + + + + + + + + + + ); +}; + +const useStyles = makeStyles({ + outline: + { + fill: "currentColor" + }, + coffee: + { + fill: "#FFDD00" + } +}); diff --git a/assets/FaviconPlaceholder.svg b/assets/FaviconPlaceholder.svg new file mode 100644 index 0000000..e87674c --- /dev/null +++ b/assets/FaviconPlaceholder.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/assets/PagePlaceholder.svg b/assets/PagePlaceholder.svg new file mode 100644 index 0000000..7ea3430 --- /dev/null +++ b/assets/PagePlaceholder.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + diff --git a/assets/global.css b/assets/global.css new file mode 100644 index 0000000..f28af09 --- /dev/null +++ b/assets/global.css @@ -0,0 +1,54 @@ +html, +body +{ + padding: 0; + margin: 0; + + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; + + overflow: hidden; +} + +* +{ + margin: 0; + box-sizing: border-box; +} + +#root > .fui-FluentProvider +{ + height: 100vh; + overflow: hidden; +} + +/* width */ +::-webkit-scrollbar +{ + width: 8px; + height: 8px; +} + +/* Track */ +::-webkit-scrollbar-track +{ + background: transparent; +} + +/* Handle */ +::-webkit-scrollbar-thumb +{ + background-color: var(--colorNeutralStroke1); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover +{ + background-color: var(--colorNeutralStroke1Hover); +} + +::-webkit-scrollbar-thumb:hover:active +{ + background-color: var(--colorNeutralStroke1Pressed); +} diff --git a/components/PromptDialog.tsx b/components/PromptDialog.tsx new file mode 100644 index 0000000..656a283 --- /dev/null +++ b/components/PromptDialog.tsx @@ -0,0 +1,48 @@ +import { useDangerStyles } from "@/hooks/useDangerStyles"; +import { Button, DialogActions, DialogBody, DialogContent, DialogSurface, DialogTitle, DialogTrigger } from "@fluentui/react-components"; + +export default function PromptDialog(props: PromptDialogProps): React.ReactElement +{ + const dangerCls = useDangerStyles(); + + return ( + + + + { props.title } + + + { props.content } + + + + + + + + + + + + + + ); +} + +export type PromptDialogProps = + { + title: string; + content: React.ReactNode; + confirmText: string; + cancelText?: string; + onConfirm: () => void; + destructive?: boolean; + }; diff --git a/contexts/DialogProvider.tsx b/contexts/DialogProvider.tsx new file mode 100644 index 0000000..3b920aa --- /dev/null +++ b/contexts/DialogProvider.tsx @@ -0,0 +1,51 @@ +import { Dialog, DialogModalType } from "@fluentui/react-components"; +import { createContext, PropsWithChildren, ReactElement } from "react"; +import PromptDialog, { PromptDialogProps } from "@/components/PromptDialog"; + +const DialogContext = createContext(null!); + +export default function DialogProvider(props: PropsWithChildren): ReactElement +{ + const [dialog, setDialog] = useState(null); + const [modalType, setModalType] = useState(undefined); + const [onDismiss, setOnDismiss] = useState<(() => void) | undefined>(undefined); + + const pushPrompt = (props: PromptDialogProps): void => + setDialog( + + ); + + const pushCustom = (dialogSurface: ReactElement, modalType?: DialogModalType, onDismiss?: () => void): void => + { + setDialog(dialogSurface); + setModalType(modalType); + setOnDismiss(() => onDismiss); + }; + + const handleOpenChange = () => + { + onDismiss?.(); + setOnDismiss(undefined); + setTimeout(() => setDialog(null), 200); + }; + + return ( + + { props.children } + + { dialog && + + { dialog } + + } + + ); +} + +export const useDialog = () => useContext(DialogContext); + +export type DialogContextType = + { + pushPrompt(props: PromptDialogProps): void; + pushCustom(dialogSurface: ReactElement, modalType?: DialogModalType, onDismiss?: () => void): void; + }; diff --git a/contexts/ThemeProvider.tsx b/contexts/ThemeProvider.tsx new file mode 100644 index 0000000..480715b --- /dev/null +++ b/contexts/ThemeProvider.tsx @@ -0,0 +1,35 @@ +import { FluentProvider, Theme, webDarkTheme, webLightTheme } from "@fluentui/react-components"; +import { createContext } from "react"; + +const ThemeContext = createContext({ theme: webLightTheme, isDark: false }); +const media: MediaQueryList = window.matchMedia("(prefers-color-scheme: dark)"); + +export default function ThemeProvider(props: React.PropsWithChildren): React.ReactElement +{ + const [isDark, setIsDark] = useState(media.matches); + const theme = useMemo(() => isDark ? webDarkTheme : webLightTheme, [isDark]); + + useEffect(() => + { + const updateTheme = (args: MediaQueryListEvent) => setIsDark(args.matches); + media.addEventListener("change", updateTheme); + + return () => media.removeEventListener("change", updateTheme); + }, []); + + return ( + + + { props.children } + + + ); +} + +export const useTheme = (): ThemeContextType => useContext(ThemeContext); + +export type ThemeContextType = + { + theme: Theme; + isDark: boolean; + }; diff --git a/data/links.ts b/data/links.ts new file mode 100644 index 0000000..16042e0 --- /dev/null +++ b/data/links.ts @@ -0,0 +1,24 @@ +import Package from "@/package.json"; + +export const buyMeACoffeeLink: string = "https://buymeacoffee.com/xfox111"; +export const bskyLink: string = "https://bsky.app/profile/xfox111.net"; +export const websiteLink: string = "https://xfox111.net"; +export const v3blogPost: string = "https://at.xfox111.net/tabs-aside-3-0"; + +const githubLink = (path: string = "."): string => + new URL(path, browser.runtime.getManifest().homepage_url).href; + +export const githubLinks = +{ + repo: githubLink(), + release: githubLink(`releases/tag/v${Package.version}`), + license: githubLink("blob/main/LICENSE"), + translationGuide: githubLink("wiki/Contribution-Guidelines#contributing-to-translations") +}; + +export const storeLink: string = + import.meta.env.FIREFOX + ? "https://addons.mozilla.org/en-US/firefox/addon/ms-edge-tabs-aside/" : + chrome.runtime.getManifest().update_url?.startsWith("https://edge.microsoft.com/") ? + "https://microsoftedge.microsoft.com/addons/detail/tabs-aside/kmnblllmalkiapkfknnlpobmjjdnlhnd" : + "https://chrome.google.com/webstore/detail/mgmjbodjgijnebfgohlnjkegdbdjgin"; diff --git a/entrypoints/background.ts b/entrypoints/background.ts new file mode 100644 index 0000000..7a6176d --- /dev/null +++ b/entrypoints/background.ts @@ -0,0 +1,338 @@ +import { collectionCount, getCollections, saveCollections } from "@/features/collectionStorage"; +import { migrateStorage } from "@/features/migration"; +import { showWelcomeDialog } from "@/features/v3welcome/utils/showWelcomeDialog"; +import { SettingsValue } from "@/hooks/useSettings"; +import { CollectionItem, GraphicsStorage } from "@/models/CollectionModels"; +import getLogger from "@/utils/getLogger"; +import { onMessage, sendMessage } from "@/utils/messaging"; +import saveTabsToCollection from "@/utils/saveTabsToCollection"; +import sendNotification from "@/utils/sendNotification"; +import { settings } from "@/utils/settings"; +import watchTabSelection from "@/utils/watchTabSelection"; +import { Tabs, Windows } from "wxt/browser"; +import { Unwatch } from "wxt/storage"; + +export default defineBackground(() => +{ + try + { + const logger = getLogger("background"); + const graphicsCache: GraphicsStorage = {}; + let listLocation: SettingsValue<"listLocation"> = "sidebar"; + + logger("Background script started"); + + // Little workaround for opening side panel + // See: https://stackoverflow.com/questions/77213045/error-sidepanel-open-may-only-be-called-in-response-to-a-user-gesture-re + settings.listLocation.getValue().then(location => listLocation = location); + settings.listLocation.watch(newLocation => listLocation = newLocation); + + browser.runtime.onInstalled.addListener(async ({ reason, previousVersion }) => + { + logger("onInstalled", reason, previousVersion); + + const previousMajor: number = previousVersion ? parseInt(previousVersion.split(".")[0]) : 0; + + if (reason === "update" && previousMajor < 3) + { + await migrateStorage(); + await showWelcomeDialog.setValue(true); + browser.runtime.reload(); + } + }); + + browser.tabs.onUpdated.addListener((_, __, tab) => + { + if (!tab.url) + return; + + graphicsCache[tab.url] = { + preview: graphicsCache[tab.url]?.preview, + icon: tab.favIconUrl ?? graphicsCache[tab.url]?.icon + }; + }); + + browser.commands.onCommand.addListener( + (command, tab) => performContextAction(command, tab!.windowId!) + ); + + onMessage("getGraphicsCache", () => graphicsCache); + onMessage("addThumbnail", ({ data }) => + { + graphicsCache[data.url] = { + preview: data.thumbnail, + icon: graphicsCache[data.url]?.icon + }; + }); + + setupContextMenu(); + async function setupContextMenu(): Promise + { + await browser.contextMenus.removeAll(); + + const items: Record = + { + "show_collections": i18n.t("actions.show_collections"), + "set_aside": i18n.t("actions.set_aside.all"), + "save": i18n.t("actions.save.all") + }; + + Object.entries(items).forEach(([id, title]) => browser.contextMenus.create({ + id, title, + visible: true, + contexts: ["action", "page"] + })); + + watchTabSelection(async selection => + { + await browser.contextMenus.update("set_aside", { + title: i18n.t(`actions.set_aside.${selection}`) + }); + await browser.contextMenus.update("save", { + title: i18n.t(`actions.save.${selection}`) + }); + }); + + browser.contextMenus.onClicked.addListener( + ({ menuItemId }, tab) => performContextAction((menuItemId as string), tab!.windowId!) + ); + } + + setupBadge(); + async function setupBadge(): Promise + { + let unwatchBadge: Unwatch | null = null; + const updateBadge = async (count: number | null) => + await browser.action.setBadgeText({ text: count && count > 0 ? count.toString() : "" }); + + if (await settings.showBadge.getValue()) + { + updateBadge(await collectionCount.getValue()); + unwatchBadge = collectionCount.watch(updateBadge); + } + + if (import.meta.env.FIREFOX) + { + await browser.action.setBadgeBackgroundColor({ color: "0f6cbd" }); + await browser.action.setBadgeTextColor({ color: "white" }); + } + + settings.showBadge.watch(async showBadge => + { + if (showBadge) + { + updateBadge(await collectionCount.getValue()); + unwatchBadge = collectionCount.watch(updateBadge); + } + else + { + unwatchBadge?.(); + await browser.action.setBadgeText({ text: "" }); + } + }); + } + + setupActionButton(); + async function setupActionButton(): Promise + { + let unwatchActionTitle: Unwatch | null = null; + + const onClickAction = async (): Promise => + { + logger("action.onClicked"); + const defaultAction = await settings.defaultSaveAction.getValue(); + await saveTabs(defaultAction === "set_aside"); + }; + + const updateTitle = async (selection: "all" | "selected"): Promise => + { + const defaultAction = await settings.defaultSaveAction.getValue(); + await browser.action.setTitle({ title: i18n.t(`actions.${defaultAction}.${selection}`) }); + }; + + const updateButton = async (action: SettingsValue<"contextAction">): Promise => + { + logger("updateButton", action); + + // Cleanup any existing behavior + browser.action.onClicked.removeListener(onClickAction); + browser.action.onClicked.removeListener(browser?.sidebarAction?.toggle); + browser.action.onClicked.removeListener(openCollectionsInTab); + + await browser.action.disable(); + await browser.action.setTitle({ title: i18n.t("manifest.name") }); + unwatchActionTitle?.(); + + if (!import.meta.env.FIREFOX) + await chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: false }); + + // Setup new behavior + if (action === "action") + { + browser.action.onClicked.addListener(onClickAction); + unwatchActionTitle = watchTabSelection(updateTitle); + await browser.action.enable(); + } + else if (action === "open") + { + await browser.action.enable(); + const location = await settings.listLocation.getValue(); + + if (location === "sidebar") + { + if (import.meta.env.FIREFOX) + browser.action.onClicked.addListener(browser.sidebarAction.toggle); + else + chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }); + } + else if (location !== "popup") + browser.action.onClicked.addListener(openCollectionsInTab); + } + }; + + updateButton(await settings.contextAction.getValue()); + settings.contextAction.watch(updateButton); + settings.listLocation.watch(async () => updateButton(await settings.contextAction.getValue())); + } + + setupCollectionView(); + async function setupCollectionView(): Promise + { + const enforcePinnedTab = async (info: Tabs.OnHighlightedHighlightInfoType): Promise => + { + logger("enforcePinnedTab", info); + + const activeWindow: Windows.Window = await browser.windows.getCurrent({ populate: true }); + + if (activeWindow.incognito) + return; + + if (!activeWindow.tabs!.some(tab => + [tab.url, tab.pendingUrl].includes(browser.runtime.getURL("/sidepanel.html"))) + ) + await browser.tabs.create({ + url: browser.runtime.getURL("/sidepanel.html"), + windowId: activeWindow.id, + active: false, + pinned: true + }); + }; + + const updateView = async (viewLocation: SettingsValue<"listLocation">): Promise => + { + logger("updateView", viewLocation); + + browser.tabs.onHighlighted.removeListener(enforcePinnedTab); + const tabs: Tabs.Tab[] = await browser.tabs.query({ + currentWindow: true, + url: browser.runtime.getURL("/sidepanel.html") + }); + await browser.tabs.remove(tabs.map(tab => tab.id!)); + + await browser.action.setPopup({ + popup: viewLocation === "popup" ? browser.runtime.getURL("/popup.html") : "" + }); + + if (import.meta.env.FIREFOX) + await browser.sidebarAction.setPanel({ + panel: viewLocation === "sidebar" ? browser.runtime.getURL("/sidepanel.html") : "" + }); + else + await chrome.sidePanel.setOptions({ enabled: viewLocation === "sidebar" }); + + if (viewLocation === "pinned") + { + await browser.tabs.create({ + url: browser.runtime.getURL("/sidepanel.html"), + active: false, + pinned: true + }); + browser.tabs.onHighlighted.addListener(enforcePinnedTab); + } + }; + + updateView(await settings.listLocation.getValue()); + settings.listLocation.watch(updateView); + } + + function performContextAction(action: string, windowId: number): void + { + if (action === "show_collections") + { + if (listLocation === "sidebar" || listLocation === "popup") + openCollectionsInView(listLocation, windowId); + else + openCollectionsInTab(); + } + else + saveTabs(action === "set_aside"); + } + + function openCollectionsInView(view: "sidebar" | "popup", windowId: number): void + { + if (view === "sidebar") + { + if (import.meta.env.FIREFOX) + browser.sidebarAction.open(); + else + chrome.sidePanel.open({ windowId }); + } + else + browser.action.openPopup(); + } + + async function openCollectionsInTab(): Promise + { + logger("openCollectionsInTab"); + + const currentWindow: Windows.Window = await browser.windows.getCurrent({ populate: true }); + + if (currentWindow.incognito) + { + await browser.windows.create({ + url: browser.runtime.getURL("/sidepanel.html"), + focused: true + }); + } + else + { + const collectionTab: Tabs.Tab | undefined = currentWindow.tabs!.find( + tab => tab.url === browser.runtime.getURL("/sidepanel.html") + ); + + if (collectionTab) + await browser.tabs.update(collectionTab.id, { active: true }); + else + await browser.tabs.create({ + url: browser.runtime.getURL("/sidepanel.html"), + active: true, + windowId: currentWindow.id + }); + } + } + + async function saveTabs(closeAfterSave: boolean): Promise + { + logger("saveTabs", closeAfterSave); + + const collection: CollectionItem = await saveTabsToCollection(closeAfterSave); + const [savedCollections, cloudIssue] = await getCollections(); + const newList = [collection, ...savedCollections]; + + await saveCollections(newList, cloudIssue === null, graphicsCache); + + sendMessage("refreshCollections", undefined); + + if (await settings.notifyOnSave.getValue()) + await sendNotification({ + title: i18n.t("notifications.tabs_saved.title"), + message: i18n.t("notifications.tabs_saved.message"), + icon: "/notification_icons/cloud_checkmark.png" + }); + } + } + catch (ex) + { + console.error(ex); + } +}); diff --git a/entrypoints/content.ts b/entrypoints/content.ts new file mode 100644 index 0000000..3145970 --- /dev/null +++ b/entrypoints/content.ts @@ -0,0 +1,46 @@ +import getLogger from "@/utils/getLogger"; +import { sendMessage } from "@/utils/messaging"; + +// This content script is injected into each browser tab. +// It's purpose is to retrive an OpenGraph thumbnail URL from the metadata + +export default defineContentScript({ + matches: [""], + runAt: "document_idle", + main +}); + +const logger = getLogger("contentScript"); + +async function main(): Promise +{ + logger("init"); + + // This method tries to sequentially retrieve thumbnails from all know meta tags. + // It stops on the first thumbnail found. + + // The order of search is: + // 1. + // 2. + // 3. + // 4. + + const thumbnailUrl: string | undefined = + document.querySelector("head meta[property='og:image']")?.content ?? + document.querySelector("head meta[name='twitter:image']")?.content ?? + document.querySelector("head link[rel=thumbnail]")?.href ?? + document.querySelector("head link[rel=image_src]")?.href; + + if (thumbnailUrl) + { + logger(`Found thumbnail for "${document.location.href}"`, thumbnailUrl); + await sendMessage("addThumbnail", { + url: document.location.href, + thumbnail: thumbnailUrl + }); + } + else + logger(`No thumbnail found for "${document.location.href}"`); + + logger("done"); +} diff --git a/entrypoints/options/hooks/useOptionsStyles.ts b/entrypoints/options/hooks/useOptionsStyles.ts new file mode 100644 index 0000000..6c00652 --- /dev/null +++ b/entrypoints/options/hooks/useOptionsStyles.ts @@ -0,0 +1,38 @@ +import { makeStyles, tokens } from "@fluentui/react-components"; + +export const useOptionsStyles = makeStyles({ + main: + { + display: "grid", + gridTemplateRows: "auto 1fr", + height: "100%" + }, + tabList: + { + flexWrap: "wrap" + }, + article: + { + display: "flex", + flexFlow: "column", + gap: tokens.spacingVerticalMNudge, + padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalM}`, + overflowY: "auto" + }, + section: + { + display: "flex", + flexFlow: "column", + alignItems: "flex-start" + }, + buttonFix: + { + minHeight: "32px" + }, + horizontalButtons: + { + display: "flex", + flexWrap: "wrap", + gap: tokens.spacingHorizontalS + } +}); diff --git a/entrypoints/options/index.html b/entrypoints/options/index.html new file mode 100644 index 0000000..423ea30 --- /dev/null +++ b/entrypoints/options/index.html @@ -0,0 +1,24 @@ + + + + + + + Tabs aside | Settings + + + + + + + +
+ + + + diff --git a/entrypoints/options/layouts/AboutSection.tsx b/entrypoints/options/layouts/AboutSection.tsx new file mode 100644 index 0000000..4153502 --- /dev/null +++ b/entrypoints/options/layouts/AboutSection.tsx @@ -0,0 +1,58 @@ +import { BuyMeACoffee20Regular } from "@/assets/BuyMeACoffee20"; +import { bskyLink, buyMeACoffeeLink, githubLinks, storeLink, websiteLink } from "@/data/links"; +import { useBmcStyles } from "@/hooks/useBmcStyles"; +import extLink from "@/utils/extLink"; +import { Body1, Button, Caption1, Link, Subtitle1, Text } from "@fluentui/react-components"; +import { PersonFeedback20Regular } from "@fluentui/react-icons"; +import { useOptionsStyles } from "../hooks/useOptionsStyles"; +import Package from "@/package.json"; + +export default function AboutSection(): React.ReactElement +{ + const cls = useOptionsStyles(); + const bmcCls = useBmcStyles(); + + return ( + <> + + { i18n.t("manifest.name") } + v{ Package.version } + + + + { i18n.t("options_page.about.developed_by") } (@xfox111.net)
+ { i18n.t("options_page.about.licensed_under") } { i18n.t("options_page.about.mit_license") } +
+ + + { i18n.t("options_page.about.translation_cta.text") }
+ + { i18n.t("options_page.about.translation_cta.button") } + +
+ + + { i18n.t("options_page.about.links.website") }
+ { i18n.t("options_page.about.links.source") }
+ { i18n.t("options_page.about.links.changelog") } +
+ +
+ + +
+ + ); +} diff --git a/entrypoints/options/layouts/ActionsSection.tsx b/entrypoints/options/layouts/ActionsSection.tsx new file mode 100644 index 0000000..dcc6832 --- /dev/null +++ b/entrypoints/options/layouts/ActionsSection.tsx @@ -0,0 +1,55 @@ +import useSettings, { SettingsValue } from "@/hooks/useSettings"; +import { Dropdown, Field, Option } from "@fluentui/react-components"; + +export default function ActionsSection(): React.ReactElement +{ + const [saveAction, setSaveAction] = useSettings("defaultSaveAction"); + const [restoreAction, setRestoreAction] = useSettings("defaultRestoreAction"); + + return ( + <> + + setSaveAction(e.optionValue as SaveActionType) } + > + { Object.entries(saveActionOptions).map(([value, label]) => + + ) } + + + + + setRestoreAction(e.optionValue as RestoreActionType) } + > + { Object.entries(restoreActionOptions).map(([value, label]) => + + ) } + + + + ); +} + +type SaveActionType = SettingsValue<"defaultSaveAction">; +type RestoreActionType = SettingsValue<"defaultRestoreAction">; + +const restoreActionOptions: Record = +{ + "open": i18n.t("options_page.actions.options.restore_actions.options.open"), + "restore": i18n.t("options_page.actions.options.restore_actions.options.restore") +}; + +const saveActionOptions: Record = +{ + "set_aside": i18n.t("options_page.actions.options.save_actions.options.set_aside"), + "save": i18n.t("options_page.actions.options.save_actions.options.save") +}; diff --git a/entrypoints/options/layouts/GeneralSection.tsx b/entrypoints/options/layouts/GeneralSection.tsx new file mode 100644 index 0000000..0c47a83 --- /dev/null +++ b/entrypoints/options/layouts/GeneralSection.tsx @@ -0,0 +1,118 @@ +import useSettings, { SettingsValue } from "@/hooks/useSettings"; +import { Button, Checkbox, Dropdown, Field, Option, OptionOnSelectData } from "@fluentui/react-components"; +import { KeyCommand20Regular } from "@fluentui/react-icons"; +import { useOptionsStyles } from "../hooks/useOptionsStyles"; + +export default function GeneralSection(): React.ReactElement +{ + const [alwaysShowToolbars, setAlwaysShowToolbars] = useSettings("alwaysShowToolbars"); + const [ignorePinned, setIgnorePinned] = useSettings("ignorePinned"); + const [deletePrompt, setDeletePrompt] = useSettings("deletePrompt"); + const [showBadge, setShowBadge] = useSettings("showBadge"); + const [notifyOnSave, setNotifyOnSave] = useSettings("notifyOnSave"); + const [dismissOnLoad, setDismissOnLoad] = useSettings("dismissOnLoad"); + const [listLocation, setListLocation] = useSettings("listLocation"); + const [contextAction, setContextAction] = useSettings("contextAction"); + + const cls = useOptionsStyles(); + + const openShortcutsPage = (): Promise => + browser.tabs.create({ + url: "chrome://extensions/shortcuts", + active: true + }); + + const handleListLocationChange = (_: any, e: OptionOnSelectData): void => + { + if (e.optionValue === "popup" && contextAction !== "open") + setContextAction("open"); + + setListLocation(e.optionValue as ListLocationType); + }; + + return ( + <> +
+ setAlwaysShowToolbars(e.checked as boolean) } /> + setIgnorePinned(!e.checked) } /> + setDeletePrompt(e.checked as boolean) } /> + setShowBadge(e.checked as boolean) } /> + setNotifyOnSave(e.checked as boolean) } /> + setDismissOnLoad(e.checked as boolean) } /> +
+ + + + { Object.entries(listLocationOptions).map(([key, value]) => + + ) } + + + + + setContextAction(e.optionValue as ContextActionType) } + disabled={ listLocation === "popup" } + > + { Object.entries(contextActionOptions).map(([key, value]) => + key === "context" && import.meta.env.FIREFOX + ? <> : + + ) } + + + + { !import.meta.env.FIREFOX && + + } + + ); +} + +type ListLocationType = SettingsValue<"listLocation">; +type ContextActionType = SettingsValue<"contextAction">; + +const listLocationOptions: Record = +{ + "sidebar": i18n.t("options_page.general.options.list_locations.options.sidebar"), + "popup": i18n.t("options_page.general.options.list_locations.options.popup"), + "tab": i18n.t("options_page.general.options.list_locations.options.tab"), + "pinned": i18n.t("options_page.general.options.list_locations.options.pinned") +}; + +const contextActionOptions: Record = +{ + "action": i18n.t("options_page.general.options.icon_action.options.action"), + "context": i18n.t("options_page.general.options.icon_action.options.context"), + "open": i18n.t("options_page.general.options.icon_action.options.open") +}; diff --git a/entrypoints/options/layouts/StorageSection.tsx b/entrypoints/options/layouts/StorageSection.tsx new file mode 100644 index 0000000..d212be4 --- /dev/null +++ b/entrypoints/options/layouts/StorageSection.tsx @@ -0,0 +1,64 @@ +import { useDialog } from "@/contexts/DialogProvider"; +import useStorageInfo from "@/hooks/useStorageInfo"; +import { Button, Field, MessageBar, MessageBarBody, MessageBarTitle, ProgressBar } from "@fluentui/react-components"; +import { ArrowDownload20Regular, ArrowUpload20Regular } from "@fluentui/react-icons"; +import { useOptionsStyles } from "../hooks/useOptionsStyles"; +import exportData from "../utils/exportData"; +import importData from "../utils/importData"; + +export default function StorageSection(): React.ReactElement +{ + const { bytesInUse, storageQuota, usedStorageRatio } = useStorageInfo(); + const [importResult, setImportResult] = useState(null); + + const dialog = useDialog(); + const cls = useOptionsStyles(); + + const handleImport = (): void => + dialog.pushPrompt({ + title: i18n.t("options_page.storage.import_prompt.title"), + confirmText: i18n.t("options_page.storage.import_prompt.proceed"), + onConfirm: () => importData().then(setImportResult), + content: ( + + + { i18n.t("options_page.storage.import_prompt.warning_title") } + + { i18n.t("options_page.storage.import_prompt.warning_text") } + + + ) + }); + + return ( + <> + = 0.8 ? "error" : undefined } + > + + + +
+ + +
+ + { importResult !== null && + + + { importResult === true ? + i18n.t("options_page.storage.import_results.success") : + i18n.t("options_page.storage.import_results.error") + } + + + } + + ); +} diff --git a/entrypoints/options/main.tsx b/entrypoints/options/main.tsx new file mode 100644 index 0000000..8e70ff6 --- /dev/null +++ b/entrypoints/options/main.tsx @@ -0,0 +1,45 @@ +import App from "@/App.tsx"; +import "@/assets/global.css"; +import { Tab, TabList } from "@fluentui/react-components"; +import ReactDOM from "react-dom/client"; +import { useOptionsStyles } from "./hooks/useOptionsStyles.ts"; +import AboutSection from "./layouts/AboutSection.tsx"; +import ActionsSection from "./layouts/ActionsSection.tsx"; +import GeneralSection from "./layouts/GeneralSection.tsx"; +import StorageSection from "./layouts/StorageSection.tsx"; + +ReactDOM.createRoot(document.getElementById("root")!).render( + + + +); + +function OptionsPage(): React.ReactElement +{ + const [selection, setSelection] = useState("general"); + const cls = useOptionsStyles(); + + return ( +
+ setSelection(data.value as SelectionType) } + > + { i18n.t("options_page.general.title") } + { i18n.t("options_page.actions.title") } + { i18n.t("options_page.storage.title") } + { i18n.t("options_page.about.title") } + + +
+ { selection === "general" && } + { selection === "actions" && } + { selection === "storage" && } + { selection === "about" && } +
+
+ ); +} + +type SelectionType = "general" | "actions" | "storage" | "about"; diff --git a/entrypoints/options/utils/exportData.ts b/entrypoints/options/utils/exportData.ts new file mode 100644 index 0000000..4c82168 --- /dev/null +++ b/entrypoints/options/utils/exportData.ts @@ -0,0 +1,16 @@ +export default async function exportData(): Promise +{ + const data: string = JSON.stringify({ + local: await browser.storage.local.get(null), + sync: await browser.storage.sync.get(null) + }); + + const element: HTMLAnchorElement = document.createElement("a"); + element.style.display = "none"; + element.href = `data:application/json;charset=utf-8,${data}`; + element.setAttribute("download", "tabs-aside_data.json"); + + document.body.appendChild(element); + element.click(); + document.body.removeChild(element); +}; diff --git a/entrypoints/options/utils/importData.ts b/entrypoints/options/utils/importData.ts new file mode 100644 index 0000000..3d66d35 --- /dev/null +++ b/entrypoints/options/utils/importData.ts @@ -0,0 +1,51 @@ +import { sendMessage } from "@/utils/messaging"; + +export default async function importData(): Promise +{ + const element: HTMLInputElement = document.createElement("input"); + element.style.display = "none"; + element.hidden = true; + element.type = "file"; + element.accept = ".json"; + + document.body.appendChild(element); + element.click(); + + await new Promise(resolve => + { + const listener = () => + { + element.removeEventListener("input", listener); + resolve(null); + }; + element.addEventListener("input", listener); + }); + + if (!element.files || element.files.length < 1) + return null; + + const file: File = element.files[0]; + const content: string = await file.text(); + + document.body.removeChild(element); + + try + { + const data: any = JSON.parse(content); + + if (data.local) + await browser.storage.local.set(data.local); + + if (data.sync) + await browser.storage.sync.set(data.sync); + } + catch (error) + { + console.error("Failed to parse JSON", error); + return false; + } + + sendMessage("refreshCollections", undefined); + + return true; +} diff --git a/entrypoints/popup.html b/entrypoints/popup.html new file mode 100644 index 0000000..4318975 --- /dev/null +++ b/entrypoints/popup.html @@ -0,0 +1,22 @@ + + + + + + + Tabs aside + + + + +
+ + + + diff --git a/entrypoints/sidepanel/components/CollectionView.styles.ts b/entrypoints/sidepanel/components/CollectionView.styles.ts new file mode 100644 index 0000000..6f666c7 --- /dev/null +++ b/entrypoints/sidepanel/components/CollectionView.styles.ts @@ -0,0 +1,101 @@ +import { makeStyles, tokens } from "@fluentui/react-components"; + +export const useStyles_CollectionView = makeStyles({ + root: + { + backgroundColor: tokens.colorNeutralBackground1, + border: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke1}`, + borderRadius: tokens.borderRadiusLarge, + display: "flex", + flexFlow: "column", + + "--border": tokens.colorNeutralForeground1, + + "&:hover .CollectionView__toolbar, &:focus-within .CollectionView__toolbar": + { + display: "flex" + }, + + "&:hover": + { + boxShadow: tokens.shadow4 + } + }, + color: + { + border: `${tokens.strokeWidthThick} solid var(--border)` + }, + verticalRoot: + { + height: "560px" + }, + empty: + { + display: "flex", + flexFlow: "column", + flexGrow: 1, + margin: `${tokens.spacingVerticalNone} ${tokens.spacingHorizontalSNudge}`, + marginBottom: tokens.spacingVerticalSNudge, + alignItems: "center", + justifyContent: "center", + gap: tokens.spacingVerticalS, + padding: `${tokens.spacingVerticalXL} ${tokens.spacingHorizontalL}`, + color: tokens.colorNeutralForeground3, + height: "144px" + }, + emptyText: + { + display: "flex", + flexFlow: "column", + alignItems: "center", + gap: tokens.spacingVerticalXS + }, + emptyCaption: + { + display: "flex", + flexWrap: "wrap", + alignItems: "center", + justifyContent: "center", + columnGap: tokens.spacingHorizontalXS + }, + list: + { + display: "grid", + padding: `${tokens.spacingVerticalXS} ${tokens.spacingHorizontalS}`, + columnGap: tokens.spacingHorizontalS, + rowGap: tokens.spacingHorizontalSNudge, + overflowX: "auto", + alignItems: "flex-end", + alignSelf: "flex-start", + maxWidth: "100%", + gridAutoFlow: "column" + }, + verticalList: + { + gridAutoFlow: "row", + width: "100%", + paddingBottom: tokens.spacingVerticalS + }, + dragOverlay: + { + cursor: "grabbing !important", + transform: "scale(1.05)", + boxShadow: `${tokens.shadow16} !important`, + "& > div": + { + pointerEvents: "none" + } + }, + sorting: + { + pointerEvents: "none" + }, + dragging: + { + visibility: "hidden" + }, + draggingOver: + { + backgroundColor: tokens.colorBrandBackground2 + } +}); diff --git a/entrypoints/sidepanel/components/CollectionView.tsx b/entrypoints/sidepanel/components/CollectionView.tsx new file mode 100644 index 0000000..77ef360 --- /dev/null +++ b/entrypoints/sidepanel/components/CollectionView.tsx @@ -0,0 +1,84 @@ +import CollectionHeader from "@/entrypoints/sidepanel/components/collections/CollectionHeader"; +import useDndItem from "@/entrypoints/sidepanel/hooks/useDndItem"; +import { useGroupColors } from "@/hooks/useGroupColors"; +import { CollectionItem } from "@/models/CollectionModels"; +import { horizontalListSortingStrategy, SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable"; +import { Body1Strong, mergeClasses } from "@fluentui/react-components"; +import { CollectionsRegular } from "@fluentui/react-icons"; +import { ReactElement } from "react"; +import CollectionContext from "../contexts/CollectionContext"; +import { useCollections } from "../contexts/CollectionsProvider"; +import { useStyles_CollectionView } from "./CollectionView.styles"; +import GroupView from "./GroupView"; +import TabView from "./TabView"; + +export default function CollectionView({ collection, index: collectionIndex, dragOverlay }: CollectionViewProps): ReactElement +{ + const { tilesView } = useCollections(); + const { + setNodeRef, + nodeProps, + setActivatorNodeRef, + activatorProps, + activeItem, isCurrentlySorting, isBeingDragged, isActiveOverThis: isOver + } = useDndItem({ id: collectionIndex.toString(), data: { indices: [collectionIndex], item: collection } }); + + const isActiveOverThis: boolean = isOver && activeItem?.item.type !== "collection"; + + const tabCount: number = useMemo(() => collection.items.flatMap(i => i.type === "group" ? i.items : i).length, [collection.items]); + const hasPinnedGroup: boolean = useMemo(() => collection.items.length > 0 && + (collection.items[0].type === "group" && collection.items[0].pinned === true), [collection.items]); + + const cls = useStyles_CollectionView(); + const colorCls = useGroupColors(); + + return ( + +
+ + + + { collection.items.length < 1 ? +
+ + { i18n.t("collections.empty") } +
+ : +
+ [collectionIndex, index].join("/")) } + strategy={ tilesView ? horizontalListSortingStrategy : verticalListSortingStrategy } + > + { collection.items.map((i, index) => + i.type === "group" ? + + : + + ) } + +
+ } +
+
+ ); +} + +export type CollectionViewProps = + { + collection: CollectionItem; + index: number; + dragOverlay?: boolean; + }; diff --git a/entrypoints/sidepanel/components/EditDialog.styles.tsx b/entrypoints/sidepanel/components/EditDialog.styles.tsx new file mode 100644 index 0000000..051efef --- /dev/null +++ b/entrypoints/sidepanel/components/EditDialog.styles.tsx @@ -0,0 +1,40 @@ +import { makeStyles, shorthands, tokens } from "@fluentui/react-components"; + +export const useStyles_EditDialog = makeStyles({ + surface: + { + "--border": tokens.colorTransparentStroke, + ...shorthands.borderWidth(tokens.strokeWidthThick), + ...shorthands.borderColor("var(--border)") + }, + content: + { + display: "flex", + flexFlow: "column", + gap: tokens.spacingVerticalS + }, + colorPicker: + { + display: "flex", + flexWrap: "wrap", + rowGap: tokens.spacingVerticalS, + columnGap: tokens.spacingVerticalS + }, + colorButton: + { + "&[aria-pressed=true]": + { + color: "var(--text) !important", + backgroundColor: "var(--border) !important", + + "& .fui-Button__icon": + { + color: "var(--text)" + } + } + }, + colorButton_icon: + { + color: "var(--border)" + } +}); diff --git a/entrypoints/sidepanel/components/EditDialog.tsx b/entrypoints/sidepanel/components/EditDialog.tsx new file mode 100644 index 0000000..86a99b3 --- /dev/null +++ b/entrypoints/sidepanel/components/EditDialog.tsx @@ -0,0 +1,142 @@ +import { getCollectionTitle } from "@/entrypoints/sidepanel/utils/getCollectionTitle"; +import { useGroupColors } from "@/hooks/useGroupColors"; +import { CollectionItem, GroupItem } from "@/models/CollectionModels"; +import * as fui from "@fluentui/react-components"; +import { Circle20Filled, CircleOff20Regular, Pin20Filled, Rename20Regular } from "@fluentui/react-icons"; +import { ReactElement } from "react"; +import { useStyles_EditDialog } from "./EditDialog.styles"; + +export default function EditDialog(props: GroupEditDialogProps): ReactElement +{ + const [title, setTitle] = useState( + (props.type === "collection" + ? props.collection?.title : + (props.group?.pinned !== true ? props.group?.title : "")) + ?? "" + ); + + const [color, setColor] = useState( + props.type === "collection" + ? props.collection?.color : + props.group?.pinned === true ? "pinned" : (props.group?.color ?? "blue") + ); + + const cls = useStyles_EditDialog(); + const colorCls = useGroupColors(); + + const handleSave = () => + { + if (props.type === "collection") + props.onSave({ + type: "collection", + timestamp: props.collection?.timestamp ?? Date.now(), + color: (color === "pinned") ? undefined : color!, + title, + items: props.collection?.items ?? [] + }); + else if (color === "pinned") + props.onSave({ + type: "group", + pinned: true, + items: props.group?.items ?? [] + }); + else + props.onSave({ + type: "group", + pinned: false, + color: color!, + title, + items: props.group?.items ?? [] + }); + }; + + return ( + + + + { + props.type === "collection" ? + i18n.t(`dialogs.edit.title.${props.collection ? "edit" : "new"}_collection`) : + i18n.t(`dialogs.edit.title.${props.group ? "edit" : "new"}_group`) + } + + + +
+ + } + disabled={ color === "pinned" } + placeholder={ + props.type === "collection" ? getCollectionTitle(props.collection) : "" + } + value={ color === "pinned" ? i18n.t("groups.pinned") : title } + onChange={ (_, e) => setTitle(e.value) } /> + + +
+ { (props.type === "group" && (!props.hidePinned || props.group?.pinned)) && + setColor("pinned") } + icon={ } + shape="circular" + > + { i18n.t("groups.pinned") } + + } + { props.type === "collection" && + setColor(undefined) } + icon={ } + shape="circular" + > + { i18n.t("colors.none") } + + } + { Object.keys(colorCls).map(i => + setColor(i as chrome.tabGroups.ColorEnum) } + className={ fui.mergeClasses(cls.colorButton, colorCls[i as chrome.tabGroups.ColorEnum]) } + icon={ { + className: cls.colorButton_icon, + children: + } } + key={ i } + shape="circular" + > + { i18n.t(`colors.${i as chrome.tabGroups.ColorEnum}`) } + + ) } +
+
+
+
+ + + + { i18n.t("common.actions.save") } + + + { i18n.t("common.actions.cancel") } + + +
+
+ ); +} + +export type GroupEditDialogProps = + { + type: "collection"; + collection?: CollectionItem; + onSave: (item: CollectionItem) => void; + } | + { + type: "group"; + hidePinned?: boolean; + group?: GroupItem; + onSave: (item: GroupItem) => void; + }; diff --git a/entrypoints/sidepanel/components/GroupView.styles.ts b/entrypoints/sidepanel/components/GroupView.styles.ts new file mode 100644 index 0000000..0dcaaea --- /dev/null +++ b/entrypoints/sidepanel/components/GroupView.styles.ts @@ -0,0 +1,148 @@ +import { makeStyles, tokens } from "@fluentui/react-components"; + +export const useStyles_GroupView = makeStyles({ + root: + { + display: "flex", + flexFlow: "column", + alignSelf: "normal", + + padding: `${tokens.spacingVerticalSNudge} ${tokens.spacingHorizontalS}`, + paddingBottom: tokens.spacingVerticalNone, + borderRadius: tokens.borderRadiusLarge, + + "&:hover .GroupView-toolbar, &:focus-within .GroupView-toolbar": + { + visibility: "visible" + }, + + "&:hover": + { + backgroundColor: tokens.colorNeutralBackground1Hover + } + }, + header: + { + display: "flex", + justifyContent: "space-between", + alignItems: "flex-end", + gap: tokens.spacingHorizontalM, + + borderBottom: `${tokens.strokeWidthThick} solid var(--border)`, + borderBottomLeftRadius: tokens.borderRadiusLarge + }, + verticalHeader: + { + borderBottomLeftRadius: tokens.borderRadiusNone + }, + title: + { + display: "grid", + gridAutoFlow: "column", + alignItems: "center", + minHeight: "12px", + minWidth: "24px", + gap: tokens.spacingHorizontalXS, + width: "max-content", + maxWidth: "160px", + + padding: `${tokens.spacingVerticalXXS} ${tokens.spacingHorizontalS}`, + paddingBottom: tokens.spacingVerticalXS, + marginBottom: "-2px", + + border: `${tokens.strokeWidthThick} solid var(--border)`, + borderRadius: `${tokens.borderRadiusLarge} ${tokens.borderRadiusLarge} ${tokens.borderRadiusNone} ${tokens.borderRadiusLarge}`, + borderBottom: "none", + backgroundColor: "var(--border)", + color: "var(--text)" + }, + verticalTitle: + { + borderBottomLeftRadius: tokens.borderRadiusNone + }, + pinned: + { + backgroundColor: "transparent" + }, + toolbar: + { + display: "flex", + gap: tokens.spacingHorizontalS, + visibility: "hidden", + + "@media (pointer: coarse)": + { + visibility: "visible" + } + }, + showToolbar: + { + visibility: "visible" + }, + openAllLink: + { + whiteSpace: "nowrap" + }, + empty: + { + display: "flex", + flexFlow: "column", + alignItems: "center", + justifyContent: "center", + color: tokens.colorNeutralForeground3, + minWidth: "160px", + height: "120px", + marginBottom: tokens.spacingVerticalSNudge + }, + verticalEmpty: + { + height: "auto", + padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalM}` + }, + list: + { + display: "flex", + columnGap: tokens.spacingHorizontalS, + rowGap: tokens.spacingHorizontalSNudge, + height: "100%" + }, + verticalList: + { + flexFlow: "column" + }, + listContainer: + { + padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalXS}`, + paddingBottom: tokens.spacingVerticalNone, + height: "100%" + }, + verticalListContainer: + { + borderLeft: `${tokens.strokeWidthThick} solid var(--border)`, + padding: tokens.spacingVerticalSNudge, + marginBottom: tokens.spacingVerticalSNudge, + borderTopLeftRadius: tokens.borderRadiusNone, + borderBottomLeftRadius: tokens.borderRadiusNone, + borderTop: "none" + }, + pinnedColor: + { + "--border": tokens.colorNeutralStrokeAccessible, + "--text": tokens.colorNeutralForeground1 + }, + dragOverlay: + { + backgroundColor: tokens.colorNeutralBackground1Hover, + transform: "scale(1.05)", + cursor: "grabbing !important", + boxShadow: `${tokens.shadow16} !important`, + "& > div": + { + pointerEvents: "none" + } + }, + dragging: + { + visibility: "hidden" + } +}); diff --git a/entrypoints/sidepanel/components/GroupView.tsx b/entrypoints/sidepanel/components/GroupView.tsx new file mode 100644 index 0000000..f4962ab --- /dev/null +++ b/entrypoints/sidepanel/components/GroupView.tsx @@ -0,0 +1,114 @@ +import GroupContext from "@/entrypoints/sidepanel/contexts/GroupContext"; +import useDndItem from "@/entrypoints/sidepanel/hooks/useDndItem"; +import { openGroup } from "@/entrypoints/sidepanel/utils/opener"; +import { useGroupColors } from "@/hooks/useGroupColors"; +import useSettings from "@/hooks/useSettings"; +import { GroupItem } from "@/models/CollectionModels"; +import { horizontalListSortingStrategy, SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable"; +import { Caption1Strong, Link, mergeClasses, Tooltip } from "@fluentui/react-components"; +import { Pin16Filled, WebAssetRegular } from "@fluentui/react-icons"; +import { ReactElement } from "react"; +import { useCollections } from "../contexts/CollectionsProvider"; +import GroupDropZone from "./collections/GroupDropZone"; +import GroupMoreMenu from "./collections/GroupMoreMenu"; +import { useStyles_GroupView } from "./GroupView.styles"; +import TabView from "./TabView"; + +export default function GroupView({ group, indices, dragOverlay }: GroupViewProps): ReactElement +{ + const [alwaysShowToolbars] = useSettings("alwaysShowToolbars"); + const { tilesView } = useCollections(); + + const groupId: string = useMemo(() => indices.join("/"), [indices]); + + const { + setNodeRef, nodeProps, + setActivatorNodeRef, activatorProps, + activeItem: active, isBeingDragged + } = useDndItem({ id: groupId, data: { indices, item: group }, disabled: group.pinned }); + + const disableDropZone: boolean = useMemo( + () => active !== null && + (active.item.type !== "tab" || (active.indices[0] === indices[0] && active.indices[1] === indices[1])), + [active, indices]); + const disableSorting: boolean = useMemo( + () => active !== null && (active.item.type !== "tab" || active.indices[0] !== indices[0]), + [active, indices]); + + const cls = useStyles_GroupView(); + const colorCls = useGroupColors(); + + return ( + +
+
+ +
+ { group.pinned === true ? + <> + + { i18n.t("groups.pinned") } + + : + + { group.title } + + } +
+ +
+ { group.items.length > 0 && + openGroup(group, false) }> + { i18n.t("groups.open") } + + } + + +
+
+ + + { group.items.length < 1 ? +
+ + { i18n.t("groups.empty") } +
+ : +
+ [...indices, index].join("/")) } + disabled={ disableSorting } + strategy={ !tilesView ? verticalListSortingStrategy : horizontalListSortingStrategy } + > + { group.items.map((i, index) => + + ) } + +
+ } +
+
+
+ ); +} + +export type GroupViewProps = + { + group: GroupItem; + indices: number[]; + dragOverlay?: boolean; + }; diff --git a/entrypoints/sidepanel/components/TabView.styles.ts b/entrypoints/sidepanel/components/TabView.styles.ts new file mode 100644 index 0000000..523ab0c --- /dev/null +++ b/entrypoints/sidepanel/components/TabView.styles.ts @@ -0,0 +1,114 @@ +import { makeStyles, tokens } from "@fluentui/react-components"; + +export const useStyles_TabView = makeStyles({ + root: + { + display: "grid", + position: "relative", + + width: "160px", + height: "120px", + marginBottom: tokens.spacingVerticalSNudge, + + border: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke3}`, + borderRadius: tokens.borderRadiusMedium, + backgroundColor: tokens.colorNeutralBackground1, + + cursor: "pointer", + textDecoration: "none !important", + userSelect: "none", + + "&:hover button, &:focus-within button": + { + display: "inline-flex" + }, + + "&:hover": + { + boxShadow: tokens.shadow4 + }, + + "&:focus-visible": + { + outline: `2px solid ${tokens.colorStrokeFocus2}` + } + }, + listView: + { + width: "100%", + height: "min-content", + marginBottom: tokens.spacingVerticalNone + }, + image: + { + zIndex: 0, + position: "absolute", + height: "100%", + width: "100%", + + borderRadius: tokens.borderRadiusMedium, + objectFit: "cover" + }, + header: + { + zIndex: 1, + alignSelf: "end", + minHeight: "32px", + + display: "grid", + gridTemplateColumns: "auto 1fr auto", + alignItems: "center", + gap: tokens.spacingHorizontalSNudge, + paddingLeft: tokens.spacingHorizontalS, + + borderBottomLeftRadius: tokens.borderRadiusMedium, + borderBottomRightRadius: tokens.borderRadiusMedium, + + backgroundColor: tokens.colorSubtleBackgroundLightAlphaHover, + color: tokens.colorNeutralForeground1, + "-webkit-backdrop-filer": "blur(4px)", + backdropFilter: "blur(4px)" + }, + icon: + { + cursor: "grab", + + "&:active": + { + cursor: "grabbing" + } + }, + title: + { + overflowX: "hidden", + justifySelf: "start", + maxWidth: "100%" + }, + deleteButton: + { + display: "none", + + "@media (pointer: coarse)": + { + display: "inline-flex" + } + }, + showDeleteButton: + { + display: "inline-flex" + }, + dragOverlay: + { + cursor: "grabbing !important", + transform: "scale(1.05)", + boxShadow: `${tokens.shadow16} !important`, + "& > div": + { + pointerEvents: "none" + } + }, + dragging: + { + visibility: "hidden" + } +}); diff --git a/entrypoints/sidepanel/components/TabView.tsx b/entrypoints/sidepanel/components/TabView.tsx new file mode 100644 index 0000000..5bad05a --- /dev/null +++ b/entrypoints/sidepanel/components/TabView.tsx @@ -0,0 +1,107 @@ +import faviconPlaceholder from "@/assets/FaviconPlaceholder.svg"; +import pagePlaceholder from "@/assets/PagePlaceholder.svg"; +import { useDialog } from "@/contexts/DialogProvider"; +import { useCollections } from "@/entrypoints/sidepanel/contexts/CollectionsProvider"; +import useDndItem from "@/entrypoints/sidepanel/hooks/useDndItem"; +import useSettings from "@/hooks/useSettings"; +import { TabItem } from "@/models/CollectionModels"; +import { Button, Caption1, Link, mergeClasses, Tooltip } from "@fluentui/react-components"; +import { Dismiss20Regular } from "@fluentui/react-icons"; +import { MouseEventHandler, ReactElement } from "react"; +import { useStyles_TabView } from "./TabView.styles"; + +export default function TabView({ tab, indices, dragOverlay }: TabViewProps): ReactElement +{ + const { removeItem, graphics, tilesView } = useCollections(); + const { + setNodeRef, setActivatorNodeRef, + nodeProps, activatorProps, isBeingDragged + } = useDndItem({ id: indices.join("/"), data: { indices, item: tab } }); + const dialog = useDialog(); + + const [deletePrompt] = useSettings("deletePrompt"); + const [showToolbar] = useSettings("alwaysShowToolbars"); + + const cls = useStyles_TabView(); + + const handleDelete: MouseEventHandler = (args) => + { + args.preventDefault(); + args.stopPropagation(); + + if (deletePrompt) + dialog.pushPrompt({ + title: i18n.t("tabs.delete"), + content: i18n.t("common.delete_prompt"), + destructive: true, + confirmText: i18n.t("common.actions.delete"), + onConfirm: () => removeItem(...indices) + }); + else + removeItem(...indices); + }; + + const handleClick: MouseEventHandler = (args) => + { + args.preventDefault(); + browser.tabs.create({ url: tab.url, active: true }); + }; + + const handleAuxClick: MouseEventHandler = (args) => + { + args.preventDefault(); + + if (args.button === 1) + browser.tabs.create({ url: tab.url, active: false }); + }; + + return ( + + { tilesView && + e.currentTarget.src = pagePlaceholder } + className={ cls.image } draggable={ false } /> + } + +
+ e.currentTarget.src = faviconPlaceholder } + height={ 20 } width={ 20 } + className={ cls.icon } draggable={ false } /> + + + + { tab.title ?? tab.url } + + + + +
+ + ); +} + +export type TabViewProps = + { + tab: TabItem; + indices: number[]; + dragOverlay?: boolean; + }; diff --git a/entrypoints/sidepanel/components/collections/CollectionHeader.tsx b/entrypoints/sidepanel/components/collections/CollectionHeader.tsx new file mode 100644 index 0000000..3b4ec45 --- /dev/null +++ b/entrypoints/sidepanel/components/collections/CollectionHeader.tsx @@ -0,0 +1,109 @@ +import { getCollectionTitle } from "@/entrypoints/sidepanel/utils/getCollectionTitle"; +import getSelectedTabs from "@/entrypoints/sidepanel/utils/getSelectedTabs"; +import useSettings from "@/hooks/useSettings"; +import { TabItem } from "@/models/CollectionModels"; +import { Button, Caption1, makeStyles, mergeClasses, Subtitle2, tokens, Tooltip } from "@fluentui/react-components"; +import { Add20Filled, Add20Regular, bundleIcon } from "@fluentui/react-icons"; +import CollectionContext, { CollectionContextType } from "../../contexts/CollectionContext"; +import { useCollections } from "../../contexts/CollectionsProvider"; +import CollectionMoreButton from "./CollectionMoreButton"; +import OpenCollectionButton from "./OpenCollectionButton"; + +export default function CollectionHeader({ dragHandleRef, dragHandleProps }: CollectionHeaderProps): React.ReactElement +{ + const { updateCollection } = useCollections(); + const { tabCount, collection, collectionIndex } = useContext(CollectionContext); + const [alwaysShowToolbars] = useSettings("alwaysShowToolbars"); + + const AddIcon = bundleIcon(Add20Filled, Add20Regular); + + const handleAddSelected = async () => + { + const newTabs: TabItem[] = await getSelectedTabs(); + updateCollection({ ...collection, items: [...collection.items, ...newTabs] }, collectionIndex); + }; + + const cls = useStyles(); + + return ( +
+
+ + + { getCollectionTitle(collection) } + + + + + { i18n.t("collections.tabs_count", [tabCount]) } + +
+ +
+ { tabCount < 1 ? + + : + + } + + +
+
+ ); +} + +export type CollectionHeaderProps = + { + dragHandleRef?: React.LegacyRef; + dragHandleProps?: React.HTMLAttributes; + }; + +const useStyles = makeStyles({ + header: + { + color: "var(--border)", + display: "grid", + gridTemplateColumns: "1fr auto", + padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalS}`, + paddingBottom: tokens.spacingVerticalS + }, + title: + { + display: "flex", + flexFlow: "column", + alignItems: "flex-start", + overflow: "hidden" + }, + titleText: + { + maxWidth: "100%" + }, + toolbar: + { + display: "none", + gap: tokens.spacingHorizontalS, + alignItems: "flex-start", + + "@media (pointer: coarse)": + { + display: "flex" + } + }, + showToolbar: + { + display: "flex" + } +}); diff --git a/entrypoints/sidepanel/components/collections/CollectionMoreButton.tsx b/entrypoints/sidepanel/components/collections/CollectionMoreButton.tsx new file mode 100644 index 0000000..e944691 --- /dev/null +++ b/entrypoints/sidepanel/components/collections/CollectionMoreButton.tsx @@ -0,0 +1,114 @@ +import { useDialog } from "@/contexts/DialogProvider"; +import { useDangerStyles } from "@/hooks/useDangerStyles"; +import useSettings from "@/hooks/useSettings"; +import { Button, Menu, MenuDivider, MenuItem, MenuList, MenuPopover, MenuTrigger, Tooltip } from "@fluentui/react-components"; +import * as ic from "@fluentui/react-icons"; +import CollectionContext, { CollectionContextType } from "../../contexts/CollectionContext"; +import { useCollections } from "../../contexts/CollectionsProvider"; +import exportCollectionToBookmarks from "../../utils/exportCollectionToBookmarks"; +import EditDialog from "../EditDialog"; + +export default function CollectionMoreButton({ onAddSelected }: CollectionMoreButtonProps): React.ReactElement +{ + const { removeItem, updateCollection } = useCollections(); + const { tabCount, hasPinnedGroup, collection, collectionIndex } = useContext(CollectionContext); + const dialog = useDialog(); + const [deletePrompt] = useSettings("deletePrompt"); + + const AddIcon = ic.bundleIcon(ic.Add20Filled, ic.Add20Regular); + const GroupIcon = ic.bundleIcon(ic.GroupList20Filled, ic.GroupList20Regular); + const EditIcon = ic.bundleIcon(ic.Edit20Filled, ic.Edit20Regular); + const DeleteIcon = ic.bundleIcon(ic.Delete20Filled, ic.Delete20Regular); + const PinnedIcon = ic.bundleIcon(ic.Pin20Filled, ic.Pin20Regular); + const BookmarkIcon = ic.bundleIcon(ic.BookmarkAdd20Filled, ic.BookmarkAdd20Regular); + + const dangerCls = useDangerStyles(); + + const handleDelete = () => + { + if (deletePrompt) + dialog.pushPrompt({ + title: i18n.t("collections.menu.delete"), + content: i18n.t("common.delete_prompt"), + destructive: true, + confirmText: i18n.t("common.actions.delete"), + onConfirm: () => removeItem(collectionIndex) + }); + else + removeItem(collectionIndex); + }; + + const handleEdit = () => + dialog.pushCustom( + updateCollection(item, collectionIndex) } /> + ); + + const handleCreateGroup = () => + dialog.pushCustom( + updateCollection({ ...collection, items: [...collection.items, group] }, collectionIndex) } /> + ); + + const handleAddPinnedGroup = () => + { + updateCollection({ + ...collection, + items: [ + { type: "group", pinned: true, items: [] }, + ...collection.items + ] + }, collectionIndex); + }; + + return ( + + + + + ); +} + +export type CollectionMoreButtonProps = + { + onAddSelected?: () => void; + }; diff --git a/entrypoints/sidepanel/components/collections/GroupDropZone.tsx b/entrypoints/sidepanel/components/collections/GroupDropZone.tsx new file mode 100644 index 0000000..0a8bbab --- /dev/null +++ b/entrypoints/sidepanel/components/collections/GroupDropZone.tsx @@ -0,0 +1,45 @@ +import { useDroppable } from "@dnd-kit/core"; +import { makeStyles, mergeClasses, tokens } from "@fluentui/react-components"; +import GroupContext, { GroupContextType } from "../../contexts/GroupContext"; + +export default function GroupDropZone({ disabled, ...props }: DropZoneProps): React.ReactElement +{ + const { group, indices } = useContext(GroupContext); + const id: string = indices.join("/") + "_dropzone"; + const { isOver, setNodeRef, active } = useDroppable({ id, data: { indices, item: group }, disabled }); + + const isDragging = !disabled && active !== null; + const cls = useStyles(); + + return ( +
+ { props.children } +
+ ); +} + +export type DropZoneProps = React.DetailedHTMLProps, HTMLDivElement> + & { + disabled?: boolean; + }; + +const useStyles = makeStyles({ + root: + { + borderRadius: tokens.borderRadiusLarge, + borderTopRightRadius: tokens.borderRadiusNone, + border: `${tokens.strokeWidthThin} solid transparent` + }, + over: + { + backgroundColor: tokens.colorBrandBackground2, + border: `${tokens.strokeWidthThin} solid ${tokens.colorBrandStroke1}` + }, + dragging: + { + border: `${tokens.strokeWidthThin} dashed ${tokens.colorNeutralStroke1}` + } +}); diff --git a/entrypoints/sidepanel/components/collections/GroupMoreMenu.tsx b/entrypoints/sidepanel/components/collections/GroupMoreMenu.tsx new file mode 100644 index 0000000..8280582 --- /dev/null +++ b/entrypoints/sidepanel/components/collections/GroupMoreMenu.tsx @@ -0,0 +1,101 @@ +import { useDialog } from "@/contexts/DialogProvider"; +import EditDialog from "@/entrypoints/sidepanel/components/EditDialog"; +import CollectionContext, { CollectionContextType } from "@/entrypoints/sidepanel/contexts/CollectionContext"; +import { useCollections } from "@/entrypoints/sidepanel/contexts/CollectionsProvider"; +import GroupContext, { GroupContextType } from "@/entrypoints/sidepanel/contexts/GroupContext"; +import getSelectedTabs from "@/entrypoints/sidepanel/utils/getSelectedTabs"; +import { useDangerStyles } from "@/hooks/useDangerStyles"; +import useSettings from "@/hooks/useSettings"; +import { TabItem } from "@/models/CollectionModels"; +import { Button, Menu, MenuItem, MenuList, MenuPopover, MenuTrigger, Tooltip } from "@fluentui/react-components"; +import * as ic from "@fluentui/react-icons"; +import { ReactElement } from "react"; +import { openGroup } from "../../utils/opener"; + +export default function GroupMoreMenu(): ReactElement +{ + const { group, indices } = useContext(GroupContext); + const { hasPinnedGroup } = useContext(CollectionContext); + const [deletePrompt] = useSettings("deletePrompt"); + const dialog = useDialog(); + const { updateGroup, removeItem, ungroup } = useCollections(); + + const dangerCls = useDangerStyles(); + + const AddIcon = ic.bundleIcon(ic.Add20Filled, ic.Add20Regular); + const UngroupIcon = ic.bundleIcon(ic.FullScreenMaximize20Filled, ic.FullScreenMaximize20Regular); + const EditIcon = ic.bundleIcon(ic.Edit20Filled, ic.Edit20Regular); + const NewWindowIcon = ic.bundleIcon(ic.WindowNew20Filled, ic.WindowNew20Regular); + const DeleteIcon = ic.bundleIcon(ic.Delete20Filled, ic.Delete20Regular); + + const handleDelete = () => + { + if (deletePrompt) + dialog.pushPrompt({ + title: i18n.t("groups.menu.delete"), + content: i18n.t("common.delete_prompt"), + confirmText: i18n.t("common.actions.delete"), + destructive: true, + onConfirm: () => removeItem(...indices) + }); + else + removeItem(...indices); + }; + + const handleEdit = () => + dialog.pushCustom( + updateGroup(item, indices[0], indices[1]) } /> + ); + + const handleAddSelected = async () => + { + const newTabs: TabItem[] = await getSelectedTabs(); + updateGroup({ ...group, items: [...group.items, ...newTabs] }, indices[0], indices[1]); + }; + + return ( + + + + + ); +} diff --git a/entrypoints/sidepanel/components/collections/OpenCollectionButton.tsx b/entrypoints/sidepanel/components/collections/OpenCollectionButton.tsx new file mode 100644 index 0000000..c5b678f --- /dev/null +++ b/entrypoints/sidepanel/components/collections/OpenCollectionButton.tsx @@ -0,0 +1,97 @@ +import { useDialog } from "@/contexts/DialogProvider"; +import useSettings from "@/hooks/useSettings"; +import browserLocaleKey from "@/utils/browserLocaleKey"; +import { Menu, MenuButtonProps, MenuItem, MenuList, MenuPopover, MenuTrigger, SplitButton } from "@fluentui/react-components"; +import * as ic from "@fluentui/react-icons"; +import CollectionContext, { CollectionContextType } from "../../contexts/CollectionContext"; +import { useCollections } from "../../contexts/CollectionsProvider"; +import { openCollection } from "../../utils/opener"; + +export default function OpenCollectionButton(): React.ReactElement +{ + const [defaultAction] = useSettings("defaultRestoreAction"); + const { removeItem } = useCollections(); + const dialog = useDialog(); + const { collection, collectionIndex } = useContext(CollectionContext); + + const OpenIcon = ic.bundleIcon(ic.Open20Filled, ic.Open20Regular); + const RestoreIcon = ic.bundleIcon(ic.ArrowExportRtl20Filled, ic.ArrowExportRtl20Regular); + const NewWindowIcon = ic.bundleIcon(ic.WindowNew20Filled, ic.WindowNew20Regular); + const InPrivateIcon = ic.bundleIcon(ic.TabInPrivate20Filled, ic.TabInPrivate20Regular); + + const handleIncognito = async () => + { + if (await browser.extension.isAllowedIncognitoAccess()) + openCollection(collection, "incognito"); + else + dialog.pushPrompt({ + title: i18n.t("collections.incognito_check.title"), + content: ( + <> + { i18n.t(`collections.incognito_check.message.${browserLocaleKey}.p1`) } +
+
+ { i18n.t(`collections.incognito_check.message.${browserLocaleKey}.p2`) } + + ), + confirmText: i18n.t("collections.incognito_check.action"), + onConfirm: async () => import.meta.env.FIREFOX ? + await browser.runtime.openOptionsPage() : + await browser.tabs.create({ + url: `chrome://extensions/?id=${browser.runtime.id}`, + active: true + }) + }); + }; + + const handleOpen = (mode: "current" | "new") => + () => openCollection(collection, mode); + + const handleRestore = async () => + { + await openCollection(collection); + removeItem(collectionIndex); + }; + + return ( + + + { (triggerProps: MenuButtonProps) => defaultAction === "restore" ? + } menuButton={ triggerProps } + primaryActionButton={ { onClick: handleRestore } } + > + { i18n.t("collections.actions.restore") } + + : + } menuButton={ triggerProps } + primaryActionButton={ { onClick: handleOpen("current") } } + > + { i18n.t("collections.actions.open") } + + } + + + + + { defaultAction === "restore" ? + } onClick={ handleOpen("current") }> + { i18n.t("collections.actions.open") } + + : + } onClick={ handleRestore }> + { i18n.t("collections.actions.restore") } + + } + } onClick={ () => handleOpen("new") }> + { i18n.t("collections.actions.new_window") } + + } onClick={ handleIncognito }> + { i18n.t(`collections.actions.incognito.${browserLocaleKey}`) } + + + + + ); +} diff --git a/entrypoints/sidepanel/contexts/CollectionContext.tsx b/entrypoints/sidepanel/contexts/CollectionContext.tsx new file mode 100644 index 0000000..a28fdd4 --- /dev/null +++ b/entrypoints/sidepanel/contexts/CollectionContext.tsx @@ -0,0 +1,14 @@ +import { CollectionItem } from "@/models/CollectionModels"; +import { createContext } from "react"; + +const CollectionContext = createContext(null!); + +export default CollectionContext; + +export type CollectionContextType = + { + collection: CollectionItem; + collectionIndex: number; + tabCount: number; + hasPinnedGroup: boolean; + }; diff --git a/entrypoints/sidepanel/contexts/CollectionsProvider.tsx b/entrypoints/sidepanel/contexts/CollectionsProvider.tsx new file mode 100644 index 0000000..634eebe --- /dev/null +++ b/entrypoints/sidepanel/contexts/CollectionsProvider.tsx @@ -0,0 +1,115 @@ +import { CloudStorageIssueType, getCollections, graphics as graphicsStorage, saveCollections } from "@/features/collectionStorage"; +import useSettings from "@/hooks/useSettings"; +import { CollectionItem, GraphicsStorage, GroupItem } from "@/models/CollectionModels"; +import getLogger from "@/utils/getLogger"; +import { onMessage } from "@/utils/messaging"; +import { createContext } from "react"; +import mergePinnedGroups from "../utils/mergePinnedGroups"; + +const logger = getLogger("CollectionsProvider"); + +const CollectionsContext = createContext(null!); + +export const useCollections = () => useContext(CollectionsContext); + +export default function CollectionsProvider({ children }: React.PropsWithChildren): React.ReactElement +{ + const [collections, setCollections] = useState(null!); + const [cloudIssue, setCloudIssue] = useState(null); + const [graphics, setGraphics] = useState({}); + const [tilesView] = useSettings("tilesView"); + + useEffect(() => + { + refreshCollections(); + onMessage("refreshCollections", refreshCollections); + }, []); + + const refreshCollections = async (): Promise => + { + const [result, issues] = await getCollections(); + setCloudIssue(issues); + setCollections(result); + setGraphics(await graphicsStorage.getValue()); + }; + + const updateStorage = async (collectionList: CollectionItem[]): Promise => + { + logger("save"); + collectionList.forEach(mergePinnedGroups); + setCollections([...collectionList]); + await saveCollections(collectionList, cloudIssue === null); + setGraphics(await graphicsStorage.getValue()); + }; + + const addCollection = (collection: CollectionItem): void => + { + updateStorage([collection, ...collections]); + }; + + const removeItem = (...indices: number[]): void => + { + if (indices.length > 2) + (collections[indices[0]].items[indices[1]] as GroupItem).items.splice(indices[2], 1); + else if (indices.length > 1) + collections[indices[0]].items.splice(indices[1], 1); + else + collections.splice(indices[0], 1); + + updateStorage(collections); + }; + + const updateCollections = (collectionList: CollectionItem[]): void => + { + updateStorage(collectionList); + }; + + const updateCollection = (collection: CollectionItem, index: number): void => + { + collections[index] = collection; + updateStorage(collections); + }; + + const updateGroup = (group: GroupItem, collectionIndex: number, groupIndex: number): void => + { + collections[collectionIndex].items[groupIndex] = group; + updateStorage(collections); + }; + + const ungroup = (collectionIndex: number, groupIndex: number): void => + { + const group = collections[collectionIndex].items[groupIndex] as GroupItem; + collections[collectionIndex].items.splice(groupIndex, 1, ...group.items); + updateStorage(collections); + }; + + return ( + + { children } + + ); +} + +export type CollectionsContextType = + { + collections: CollectionItem[] | null; + cloudIssue: CloudStorageIssueType | null; + graphics: GraphicsStorage; + tilesView: boolean; + + refreshCollections: () => Promise; + addCollection: (collection: CollectionItem) => void; + + updateCollections: (collections: CollectionItem[]) => void; + updateCollection: (collection: CollectionItem, index: number) => void; + updateGroup: (group: GroupItem, collectionIndex: number, groupIndex: number) => void; + ungroup: (collectionIndex: number, groupIndex: number) => void; + + removeItem: (...indices: number[]) => void; + }; diff --git a/entrypoints/sidepanel/contexts/GroupContext.tsx b/entrypoints/sidepanel/contexts/GroupContext.tsx new file mode 100644 index 0000000..d0d8c06 --- /dev/null +++ b/entrypoints/sidepanel/contexts/GroupContext.tsx @@ -0,0 +1,12 @@ +import { GroupItem } from "@/models/CollectionModels"; +import { createContext } from "react"; + +const GroupContext = createContext(null!); + +export default GroupContext; + +export type GroupContextType = + { + group: GroupItem; + indices: number[]; + }; diff --git a/entrypoints/sidepanel/hooks/useDndItem.ts b/entrypoints/sidepanel/hooks/useDndItem.ts new file mode 100644 index 0000000..a2bb2e5 --- /dev/null +++ b/entrypoints/sidepanel/hooks/useDndItem.ts @@ -0,0 +1,61 @@ +import { CollectionItem, GroupItem, TabItem } from "@/models/CollectionModels"; +import { useSortable } from "@dnd-kit/sortable"; +import { Arguments } from "@dnd-kit/sortable/dist/hooks/useSortable"; + +export default function useDndItem(args: Arguments): DndItemHook +{ + const { + setActivatorNodeRef, setNodeRef, + transform, attributes, listeners, + active, over, + isDragging, + isSorting, + isOver + } = useSortable({ transition: null, ...args }); + + return { + setActivatorNodeRef, + setNodeRef, + nodeProps: + { + style: + { + transform: transform ? `translate(${transform.x}px, ${transform.y}px)` : undefined + }, + ...attributes + }, + activatorProps: + { + ...listeners, + style: + { + cursor: args.disabled ? undefined : "grab" + } + }, + activeItem: active ? { ...active.data.current, id: active.id } as DndItem : null, + overItem: over ? { ...over.data.current, id: over.id } as DndItem : null, + isBeingDragged: isDragging, + isCurrentlySorting: isSorting, + isActiveOverThis: isOver + }; +} + +export type DndItem = + { + id: string; + indices: number[]; + item: (TabItem | CollectionItem | GroupItem); + }; + +export type DndItemHook = + { + setNodeRef: (element: HTMLElement | null) => void; + setActivatorNodeRef: (element: HTMLElement | null) => void; + nodeProps: React.HTMLAttributes; + activatorProps: React.HTMLAttributes; + activeItem: DndItem | null; + overItem: DndItem | null; + isBeingDragged: boolean; + isCurrentlySorting: boolean; + isActiveOverThis: boolean; + }; diff --git a/entrypoints/sidepanel/index.html b/entrypoints/sidepanel/index.html new file mode 100644 index 0000000..2611a2e --- /dev/null +++ b/entrypoints/sidepanel/index.html @@ -0,0 +1,18 @@ + + + + + + + Tabs aside + + + + + + +
+ + + + diff --git a/entrypoints/sidepanel/layouts/collections/CollectionListView.styles.ts b/entrypoints/sidepanel/layouts/collections/CollectionListView.styles.ts new file mode 100644 index 0000000..cd13917 --- /dev/null +++ b/entrypoints/sidepanel/layouts/collections/CollectionListView.styles.ts @@ -0,0 +1,51 @@ +import { makeStyles, tokens } from "@fluentui/react-components"; + +export const useStyles_CollectionListView = makeStyles({ + root: + { + display: "flex", + flexFlow: "column", + gap: tokens.spacingVerticalM, + padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalS}`, + overflowX: "hidden", + overflowY: "auto" + }, + collectionList: + { + display: "flex", + flexFlow: "column", + gap: tokens.spacingVerticalM + }, + searchBar: + { + boxShadow: tokens.shadow2 + }, + emptySearch: + { + display: "flex", + flexFlow: "column", + flexGrow: 1, + alignItems: "center", + justifyContent: "center", + gap: tokens.spacingVerticalS + }, + empty: + { + display: "flex", + flexFlow: "column", + alignItems: "center", + justifyContent: "center", + gap: tokens.spacingVerticalS, + padding: `${tokens.spacingVerticalM} ${tokens.spacingHorizontalM}`, + color: tokens.colorNeutralForeground2 + }, + msgBar: + { + flex: "none" + }, + listView: + { + display: "grid", + gridTemplateColumns: "repeat(auto-fit, minmax(360px, 1fr))" + } +}); diff --git a/entrypoints/sidepanel/layouts/collections/CollectionListView.tsx b/entrypoints/sidepanel/layouts/collections/CollectionListView.tsx new file mode 100644 index 0000000..1ec1889 --- /dev/null +++ b/entrypoints/sidepanel/layouts/collections/CollectionListView.tsx @@ -0,0 +1,149 @@ +import CollectionView from "@/entrypoints/sidepanel/components/CollectionView"; +import GroupView from "@/entrypoints/sidepanel/components/GroupView"; +import { DndItem } from "@/entrypoints/sidepanel/hooks/useDndItem"; +import CloudIssueMessages from "@/entrypoints/sidepanel/layouts/collections/messages/CloudIssueMessages"; +import CtaMessage from "@/entrypoints/sidepanel/layouts/collections/messages/CtaMessage"; +import filterCollections, { CollectionFilterType } from "@/entrypoints/sidepanel/utils/filterCollections"; +import sortCollections from "@/entrypoints/sidepanel/utils/sortCollections"; +import useSettings from "@/hooks/useSettings"; +import { CollectionItem } from "@/models/CollectionModels"; +import { DndContext, DragEndEvent, DragOverlay, DragStartEvent, MouseSensor, TouchSensor, useSensor, useSensors } from "@dnd-kit/core"; +import { rectSortingStrategy, SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable"; +import { Body1, Button, Caption1, mergeClasses, Subtitle2 } from "@fluentui/react-components"; +import { ArrowUndo20Regular, SearchInfo24Regular, Sparkle48Regular } from "@fluentui/react-icons"; +import { ReactElement } from "react"; +import TabView from "../../components/TabView"; +import CollectionContext from "../../contexts/CollectionContext"; +import { useCollections } from "../../contexts/CollectionsProvider"; +import applyReorder from "../../utils/dnd/applyReorder"; +import { collisionDetector } from "../../utils/dnd/collisionDetector"; +import { useStyles_CollectionListView } from "./CollectionListView.styles"; +import SearchBar from "./SearchBar"; +import StorageCapacityIssueMessage from "./messages/StorageCapacityIssueMessage"; + +export default function CollectionListView(): ReactElement +{ + const { tilesView, updateCollections, collections } = useCollections(); + + const [sortMode, setSortMode] = useSettings("sortMode"); + const [query, setQuery] = useState(""); + const [colors, setColors] = useState([]); + + const [active, setActive] = useState(null); + + const sensors = useSensors( + useSensor(MouseSensor, { activationConstraint: { delay: 100, tolerance: 0 } }), + useSensor(TouchSensor, { activationConstraint: { delay: 300, tolerance: 20 } }) + ); + + const resultList = useMemo( + () => sortCollections(filterCollections(collections, { query, colors }), sortMode), + [query, colors, sortMode, collections] + ); + + const cls = useStyles_CollectionListView(); + + const resetFilter = useCallback(() => + { + setQuery(""); + setColors([]); + }, []); + + const handleDragStart = (event: DragStartEvent): void => + { + setActive(event.active.data.current as DndItem); + }; + + const handleDragEnd = (args: DragEndEvent): void => + { + setActive(null); + const result: CollectionItem[] | null = applyReorder(resultList, args); + + if (result !== null) + { + updateCollections(result); + if (sortMode !== "custom") + setSortMode("custom"); + } + }; + + if (sortMode === null || collections === null) + return <>; + + if (collections.length < 1) + return ( +
+ + { i18n.t("main.list.empty.title") } + { i18n.t("main.list.empty.message") } +
+ ); + + return ( +
+ + + + + + + { resultList.length < 1 ? +
+ + { i18n.t("main.list.empty_search.title") } + { i18n.t("main.list.empty_search.message") } + +
+ : +
+ + index.toString()) } + strategy={ tilesView ? verticalListSortingStrategy : rectSortingStrategy } + > + { resultList.map((collection, index) => + + ) } + + + + { active && + <> + { active.item.type === "collection" && + + } + { active.item.type === "group" && + + + + } + { active.item.type === "tab" && + + } + + } + + +
+ } +
+ ); +} diff --git a/entrypoints/sidepanel/layouts/collections/FilterCollectionsButton.tsx b/entrypoints/sidepanel/layouts/collections/FilterCollectionsButton.tsx new file mode 100644 index 0000000..a36842b --- /dev/null +++ b/entrypoints/sidepanel/layouts/collections/FilterCollectionsButton.tsx @@ -0,0 +1,71 @@ +import { useGroupColors } from "@/hooks/useGroupColors"; +import * as fui from "@fluentui/react-components"; +import * as ic from "@fluentui/react-icons"; +import { CollectionFilterType } from "../../utils/filterCollections"; + +export default function FilterCollectionsButton({ value, onChange }: FilterCollectionsButtonProps): React.ReactElement +{ + const cls = useStyles(); + const colorCls = useGroupColors(); + + const ColorFilterIcon = ic.bundleIcon(ic.Color20Filled, ic.Color20Regular); + const ColorIcon = ic.bundleIcon(ic.Circle20Filled, ic.CircleHalfFill20Regular); + const NoColorIcon = ic.bundleIcon(ic.CircleOffFilled, ic.CircleOffRegular); + const AnyColorIcon = ic.bundleIcon(ic.PhotoFilter20Filled, ic.PhotoFilter20Regular); + + return ( + + onChange?.(e.checkedItems.includes("any") ? [] : e.checkedItems as CollectionFilterType["colors"]) + } + > + + + + } /> + + + + + + }> + { i18n.t("colors.any") } + + + }> + { i18n.t("colors.none") } + + + { Object.keys(colorCls).map(i => + + } + > + { i18n.t(`colors.${i as chrome.tabGroups.ColorEnum}`) } + + ) } + + + + ); +} + +export type FilterCollectionsButtonProps = + { + value?: CollectionFilterType["colors"]; + onChange?: (value: CollectionFilterType["colors"]) => void; + }; + +const useStyles = fui.makeStyles({ + colorIcon: + { + color: "var(--border)" + } +}); diff --git a/entrypoints/sidepanel/layouts/collections/SearchBar.tsx b/entrypoints/sidepanel/layouts/collections/SearchBar.tsx new file mode 100644 index 0000000..a525e19 --- /dev/null +++ b/entrypoints/sidepanel/layouts/collections/SearchBar.tsx @@ -0,0 +1,51 @@ +import { Button, Input, makeStyles, tokens, Tooltip } from "@fluentui/react-components"; +import { ArrowUndo20Filled, ArrowUndo20Regular, bundleIcon, Search20Regular } from "@fluentui/react-icons"; +import { CollectionFilterType } from "../../utils/filterCollections"; +import { CollectionSortMode } from "../../utils/sortCollections"; +import FilterCollectionsButton from "./FilterCollectionsButton"; +import SortCollectionsButton from "./SortCollectionsButton"; + +export default function SearchBar(props: SearchBarProps): React.ReactElement +{ + const cls = useStyles(); + + const ResetIcon = bundleIcon(ArrowUndo20Filled, ArrowUndo20Regular); + + return ( + } + placeholder={ i18n.t("main.list.searchbar.title") } + value={ props.query } onChange={ (_, e) => props.onQueryChange?.(e.value) } + contentAfter={ + <> + { (props.query || (props.filter && props.filter.length > 0)) && + + + + + } + + { cloudIssue === "merge_conflict" && + + + { i18n.t("merge_conflict_message.title") } + { i18n.t("merge_conflict_message.message") } + + + + + + + } + + ); +} diff --git a/entrypoints/sidepanel/layouts/collections/messages/CtaMessage.tsx b/entrypoints/sidepanel/layouts/collections/messages/CtaMessage.tsx new file mode 100644 index 0000000..847f065 --- /dev/null +++ b/entrypoints/sidepanel/layouts/collections/messages/CtaMessage.tsx @@ -0,0 +1,60 @@ +import { BuyMeACoffee20Regular } from "@/assets/BuyMeACoffee20"; +import { buyMeACoffeeLink, storeLink } from "@/data/links"; +import { useBmcStyles } from "@/hooks/useBmcStyles"; +import extLink from "@/utils/extLink"; +import { Button, Link, MessageBar, MessageBarActions, MessageBarBody, MessageBarProps, MessageBarTitle } from "@fluentui/react-components"; +import { DismissRegular, HeartFilled } from "@fluentui/react-icons"; +import { ReactElement } from "react"; + +export default function CtaMessage(props: MessageBarProps): ReactElement +{ + const [counter, setCounter] = useState(0); + const bmcCls = useBmcStyles(); + + useEffect(() => + { + ctaCounter.getValue().then(c => + { + if (c >= 0) + { + setCounter(c); + ctaCounter.setValue(c + 1); + } + }); + }, []); + + const resetCounter = async (counter: number) => + { + await ctaCounter.setValue(counter); + setCounter(counter); + }; + + if (counter < 50) + return <>; + + return ( + } { ...props }> + + { i18n.t("cta_message.title") } + { i18n.t("cta_message.message") } { i18n.t("cta_message.feedback") } + + } appearance="transparent" onClick={ () => resetCounter(0) } /> + } + > + + + + ); +} + +const ctaCounter = storage.defineItem("local:ctaCounter", { fallback: 0 }); diff --git a/entrypoints/sidepanel/layouts/collections/messages/StorageCapacityIssueMessage.tsx b/entrypoints/sidepanel/layouts/collections/messages/StorageCapacityIssueMessage.tsx new file mode 100644 index 0000000..537981e --- /dev/null +++ b/entrypoints/sidepanel/layouts/collections/messages/StorageCapacityIssueMessage.tsx @@ -0,0 +1,21 @@ +import useStorageInfo from "@/hooks/useStorageInfo"; +import { MessageBar, MessageBarBody, MessageBarProps, MessageBarTitle } from "@fluentui/react-components"; + +export default function StorageCapacityIssueMessage(props: MessageBarProps): JSX.Element +{ + const { usedStorageRatio } = useStorageInfo(); + + if (usedStorageRatio < 0.8) + return <>; + + return ( + + + + { i18n.t("storage_full_message.title", [(usedStorageRatio * 100).toFixed(1)]) } + + { i18n.t("storage_full_message.message") } + + + ); +} diff --git a/entrypoints/sidepanel/layouts/header/ActionButton.tsx b/entrypoints/sidepanel/layouts/header/ActionButton.tsx new file mode 100644 index 0000000..810b1a5 --- /dev/null +++ b/entrypoints/sidepanel/layouts/header/ActionButton.tsx @@ -0,0 +1,74 @@ +import { useCollections } from "@/entrypoints/sidepanel/contexts/CollectionsProvider"; +import useSettings, { SettingsValue } from "@/hooks/useSettings"; +import saveTabsToCollection from "@/utils/saveTabsToCollection"; +import watchTabSelection from "@/utils/watchTabSelection"; +import { Menu, MenuButtonProps, MenuItem, MenuList, MenuPopover, MenuTrigger, SplitButton } from "@fluentui/react-components"; +import * as ic from "@fluentui/react-icons"; +import { ReactElement } from "react"; + +export default function ActionButton(): ReactElement +{ + const { addCollection } = useCollections(); + const [defaultAction] = useSettings("defaultSaveAction"); + const [selection, setSelection] = useState<"all" | "selected">("all"); + + const handleAction = async (primary: boolean) => + { + const colection = await saveTabsToCollection(primary === (defaultAction === "set_aside")); + addCollection(colection); + }; + + useEffect(() => + { + return watchTabSelection(setSelection); + }, []); + + if (defaultAction === null) + return
; + + const primaryActionKey: ActionsKey = `${defaultAction}.${selection}`; + const PrimaryIcon = actionIcons[primaryActionKey]; + const secondaryActionKey: ActionsKey = `${defaultAction === "save" ? "set_aside" : "save"}.${selection}`; + const SecondaryIcon = actionIcons[secondaryActionKey]; + + return ( + + + { (triggerProps: MenuButtonProps) => ( + } + menuButton={ triggerProps } + primaryActionButton={ { onClick: () => handleAction(true) } } + > + { i18n.t(`actions.${primaryActionKey}`) } + + ) } + + + + + } onClick={ () => handleAction(false) }> + { i18n.t(`actions.${secondaryActionKey}`) } + + + + + ); +} + +const actionIcons: Record = +{ + "save.all": ic.bundleIcon(ic.SaveArrowRight20Filled, ic.SaveArrowRight20Regular), + "save.selected": ic.bundleIcon(ic.SaveCopy20Filled, ic.SaveCopy20Regular), + "set_aside.all": ic.bundleIcon(ic.ArrowRight20Filled, ic.ArrowRight20Regular), + "set_aside.selected": ic.bundleIcon(ic.CopyArrowRight20Filled, ic.CopyArrowRight20Regular) +}; + +export type ActionsKey = `${SettingsValue<"defaultSaveAction">}.${"all" | "selected"}`; + +export type ActionsValue = + { + label: string; + icon: ic.FluentIcon; + }; diff --git a/entrypoints/sidepanel/layouts/header/Header.tsx b/entrypoints/sidepanel/layouts/header/Header.tsx new file mode 100644 index 0000000..22150b9 --- /dev/null +++ b/entrypoints/sidepanel/layouts/header/Header.tsx @@ -0,0 +1,53 @@ +import { useDialog } from "@/contexts/DialogProvider"; +import { useCollections } from "@/entrypoints/sidepanel/contexts/CollectionsProvider"; +import { Button, makeStyles, tokens, Tooltip } from "@fluentui/react-components"; +import { CollectionsAddRegular } from "@fluentui/react-icons"; +import { ReactElement } from "react"; +import EditDialog from "../../components/EditDialog"; +import ActionButton from "./ActionButton"; +import MoreButton from "./MoreButton"; + +export default function Header(): ReactElement +{ + const { addCollection } = useCollections(); + const dialog = useDialog(); + const cls = useStyles(); + + const handleCreateCollection = () => + dialog.pushCustom( + + ); + + return ( +
+ + +
+ + +
+
+ ); +} + +const useStyles = makeStyles({ + header: + { + display: "flex", + justifyContent: "space-between", + padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalS}`, + gap: tokens.spacingHorizontalS + }, + headerSecondary: + { + display: "flex", + gap: tokens.spacingHorizontalXS + } +}); diff --git a/entrypoints/sidepanel/layouts/header/MoreButton.tsx b/entrypoints/sidepanel/layouts/header/MoreButton.tsx new file mode 100644 index 0000000..5359855 --- /dev/null +++ b/entrypoints/sidepanel/layouts/header/MoreButton.tsx @@ -0,0 +1,85 @@ +import { BuyMeACoffee20Filled, BuyMeACoffee20Regular } from "@/assets/BuyMeACoffee20"; +import { buyMeACoffeeLink, githubLinks, storeLink } from "@/data/links"; +import useSettings from "@/hooks/useSettings"; +import extLink from "@/utils/extLink"; +import sendNotification from "@/utils/sendNotification"; +import * as fui from "@fluentui/react-components"; +import * as ic from "@fluentui/react-icons"; +import { ReactElement } from "react"; + +export default function MoreButton(): ReactElement +{ + const [tilesView, setTilesView] = useSettings("tilesView"); + + const SettingsIcon: ic.FluentIcon = ic.bundleIcon(ic.Settings20Filled, ic.Settings20Regular); + const ViewIcon: ic.FluentIcon = ic.bundleIcon(ic.GridKanban20Filled, ic.GridKanban20Regular); + const FeedbackIcon: ic.FluentIcon = ic.bundleIcon(ic.PersonFeedback20Filled, ic.PersonFeedback20Regular); + const LearnIcon: ic.FluentIcon = ic.bundleIcon(ic.QuestionCircle20Filled, ic.QuestionCircle20Regular); + const BmcIcon: ic.FluentIcon = ic.bundleIcon(BuyMeACoffee20Filled, BuyMeACoffee20Regular); + + return ( + setTilesView(e.checkedItems.length > 0) } + > + + + } /> + + + + + + + } onClick={ () => browser.runtime.openOptionsPage() }> + { i18n.t("options_page.title") } + + }> + { i18n.t("main.header.menu.tiles_view") } + + + + + } { ...extLink(buyMeACoffeeLink) }> + { i18n.t("common.cta.sponsor") } + + } { ...extLink(storeLink) } > + { i18n.t("common.cta.feedback") } + + } { ...extLink(githubLinks.release) } > + { i18n.t("main.header.menu.changelog") } + + + { import.meta.env.DEV && + + Dev tools + } + onClick={ () => document.location.reload() } + > + Reload page + + } + onClick={ () => browser.tabs.create({ url: browser.runtime.getURL("/sidepanel.html"), active: true }) } + > + Open in tab + + } + onClick={ async () => await sendNotification({ + icon: "/notification_icons/cloud_error.png", + message: "Notification message", + title: "Notification title" + }) } + > + Show test notification + + + } + + + + ); +} diff --git a/entrypoints/sidepanel/main.tsx b/entrypoints/sidepanel/main.tsx new file mode 100644 index 0000000..a9a2560 --- /dev/null +++ b/entrypoints/sidepanel/main.tsx @@ -0,0 +1,44 @@ +import App from "@/App.tsx"; +import "@/assets/global.css"; +import { useLocalMigration } from "@/features/migration"; +import useWelcomeDialog from "@/features/v3welcome/hooks/useWelcomeDialog"; +import { Divider, makeStyles } from "@fluentui/react-components"; +import ReactDOM from "react-dom/client"; +import CollectionsProvider from "./contexts/CollectionsProvider"; +import CollectionListView from "./layouts/collections/CollectionListView"; +import Header from "./layouts/header/Header"; + +ReactDOM.createRoot(document.getElementById("root")!).render( + + + +); + +document.title = i18n.t("manifest.name"); + +function MainPage(): React.ReactElement +{ + const cls = useStyles(); + + useLocalMigration(); + useWelcomeDialog(); + + return ( + +
+
+ + +
+
+ ); +} + +const useStyles = makeStyles({ + main: + { + display: "grid", + gridTemplateRows: "auto auto 1fr", + height: "100vh" + } +}); diff --git a/entrypoints/sidepanel/utils/dnd/applyReorder.ts b/entrypoints/sidepanel/utils/dnd/applyReorder.ts new file mode 100644 index 0000000..b5b29a2 --- /dev/null +++ b/entrypoints/sidepanel/utils/dnd/applyReorder.ts @@ -0,0 +1,61 @@ +import { CollectionItem, GroupItem, TabItem } from "@/models/CollectionModels"; +import { DragEndEvent } from "@dnd-kit/core"; +import { arrayMove } from "@dnd-kit/sortable"; +import { DndItem } from "../../hooks/useDndItem"; + +export default function applyReorder(collections: CollectionItem[], { over, active }: DragEndEvent): null | CollectionItem[] +{ + if (!over || active.id === over.id) + return null; + + const activeItem: DndItem = active.data.current as DndItem; + const overItem: DndItem = over.data.current as DndItem; + + console.log("DragEnd", `active: ${active.id} ${activeItem.item.type}`, `over: ${over.id} ${overItem.item.type}`); + + let newList: CollectionItem[] = [ + ...collections.map(collection => ({ + ...collection, + items: collection.items.map(item => + item.type === "group" ? + { ...item, items: item.items.map(tab => ({ ...tab })) } : + { ...item } + ) + })) + ]; + + if (activeItem.item.type === "collection") + { + newList = arrayMove( + newList, + activeItem.indices[0], + overItem.indices[0] + ); + + return newList; + } + + const sourceItem: GroupItem | CollectionItem = activeItem.indices.length > 2 ? + (newList[activeItem.indices[0]].items[activeItem.indices[1]] as GroupItem) : + newList[activeItem.indices[0]]; + + if ((over.id as string).endsWith("_dropzone") || overItem.item.type === "collection") + { + const destItem: GroupItem | CollectionItem = overItem.indices.length > 1 ? + (newList[overItem.indices[0]].items[overItem.indices[1]] as GroupItem) : + newList[overItem.indices[0]]; + + destItem.items.push(activeItem.item as any); + sourceItem.items.splice(activeItem.indices[activeItem.indices.length - 1], 1); + } + else + { + sourceItem.items = arrayMove( + sourceItem.items, + activeItem.indices[activeItem.indices.length - 1], + overItem.indices[overItem.indices.length - 1] + ); + } + + return newList; +} diff --git a/entrypoints/sidepanel/utils/dnd/collisionDetector.ts b/entrypoints/sidepanel/utils/dnd/collisionDetector.ts new file mode 100644 index 0000000..b175d20 --- /dev/null +++ b/entrypoints/sidepanel/utils/dnd/collisionDetector.ts @@ -0,0 +1,121 @@ +import { ClientRect, Collision, CollisionDescriptor, CollisionDetection } from "@dnd-kit/core"; +import { DndItem } from "../../hooks/useDndItem"; +import { centerOfRectangle, distanceBetween, getIntersectionRatio, getMaxIntersectionRatio, getRectSideCoordinates, sortCollisionsAsc } from "./dndUtils"; + +export function collisionDetector(vertical?: boolean): CollisionDetection +{ + return (args): Collision[] => + { + const { collisionRect, droppableContainers, droppableRects, active, pointerCoordinates } = args; + const activeItem = active.data.current as DndItem; + + if (!pointerCoordinates) + return []; + + const collisions: CollisionDescriptor[] = []; + const centerRect = centerOfRectangle( + collisionRect, + collisionRect.left, + collisionRect.top + ); + + for (const droppableContainer of droppableContainers) + { + const { id, data } = droppableContainer; + const rect = droppableRects.get(id); + + const droppableItem: DndItem = data.current as DndItem; + + if (!rect) + continue; + + let value: number = 0; + + if (activeItem.item.type === "collection") + { + if (droppableItem.item.type !== "collection") + continue; + + value = distanceBetween(centerOfRectangle(rect), centerRect); + collisions.push({ id, data: { droppableContainer, value } }); + continue; + } + + const intersectionRatio: number = getIntersectionRatio(rect, collisionRect); + const intersectionCoefficient: number = intersectionRatio / getMaxIntersectionRatio(rect, collisionRect); + + if (droppableItem.item.type === "collection") + { + if (activeItem.indices.length === 2 && activeItem.indices[0] === droppableItem.indices[0]) + continue; + + if (intersectionCoefficient < 0.7 && activeItem.item.type === "tab") + continue; + + if (activeItem.indices.length === 3 && activeItem.indices[0] === droppableItem.indices[0]) + { + const [collectionId, groupId] = activeItem.indices; + const groupRect: ClientRect | undefined = droppableRects.get(`${collectionId}/${groupId}`); + + if (!groupRect) + continue; + + value = 1 / (intersectionRatio - getIntersectionRatio(groupRect, collisionRect)); + } + else + { + value = 1 / intersectionRatio; + } + } + else if (droppableItem.item.type === "group" && (id as string).endsWith("_dropzone")) + { + if (activeItem.item.type === "group") + continue; + + if ( + activeItem.indices.length === 3 && + activeItem.indices[0] === droppableItem.indices[0] && + activeItem.indices[1] === droppableItem.indices[1] + ) + continue; + + if (intersectionCoefficient < 0.5) + continue; + + value = 1 / intersectionRatio; + } + else if (activeItem.indices.length === droppableItem.indices.length) + { + if (activeItem.indices[0] !== droppableItem.indices[0]) + continue; + + if (activeItem.indices.length === 3 && activeItem.indices[1] !== droppableItem.indices[1]) + continue; + + if (droppableItem.item.type === "group" && droppableItem.item.pinned === true) + continue; + + if (activeItem.item.type === "tab" && droppableItem.item.type === "tab") + { + value = distanceBetween(centerOfRectangle(rect), centerRect); + } + else + { + const activeIndex: number = activeItem.indices[activeItem.indices.length - 1]; + const droppableIndex: number = droppableItem.indices[droppableItem.indices.length - 1]; + const before: boolean = activeIndex < droppableIndex; + + value = distanceBetween( + getRectSideCoordinates(rect, before, vertical), + getRectSideCoordinates(collisionRect, before, vertical) + ); + } + } + + if ((value > 0 && value < Number.POSITIVE_INFINITY) || active.id === id) + collisions.push({ id, data: { droppableContainer, value } }); + }; + + return collisions.sort(sortCollisionsAsc); + }; +} diff --git a/entrypoints/sidepanel/utils/dnd/dndUtils.ts b/entrypoints/sidepanel/utils/dnd/dndUtils.ts new file mode 100644 index 0000000..389bb3b --- /dev/null +++ b/entrypoints/sidepanel/utils/dnd/dndUtils.ts @@ -0,0 +1,128 @@ +import { ClientRect, CollisionDescriptor } from "@dnd-kit/core"; +import { Coordinates } from "@dnd-kit/utilities"; + +export function getRectSideCoordinates(rect: ClientRect, before: boolean, vertical?: boolean) +{ + if (before) + return vertical ? bottomsideOfRect(rect) : rightsideOfRect(rect); + + return vertical ? topsideOfRect(rect) : leftsideOfRect(rect); +} + +export function getMaxIntersectionRatio(entry: ClientRect, target: ClientRect): number +{ + const entrySize = entry.width * entry.height; + const targetSize = target.width * target.height; + + return Math.min(targetSize / entrySize, entrySize / targetSize); +} + +function topsideOfRect(rect: ClientRect): Coordinates +{ + const { left, top } = rect; + + return { + x: left + rect.width * 0.5, + y: top + }; +} + +function bottomsideOfRect(rect: ClientRect): Coordinates +{ + const { left, bottom } = rect; + return { + x: left + rect.width * 0.5, + y: bottom + }; +} + +function rightsideOfRect(rect: ClientRect): Coordinates +{ + const { right, top } = rect; + return { + x: right, + y: top + rect.height * 0.5 + }; +} + +function leftsideOfRect(rect: ClientRect): Coordinates +{ + const { left, top } = rect; + return { + x: left, + y: top + rect.height * 0.5 + }; +} + +/* + * MIT License + * + * Copyright (c) 2021, ClaudÊric Demers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +export function distanceBetween(p1: Coordinates, p2: Coordinates) +{ + return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)); +} + +export function sortCollisionsAsc( + { data: { value: a } }: CollisionDescriptor, + { data: { value: b } }: CollisionDescriptor +) +{ + return a - b; +} + +export function getIntersectionRatio(entry: ClientRect, target: ClientRect): number +{ + const top = Math.max(target.top, entry.top); + const left = Math.max(target.left, entry.left); + const right = Math.min(target.left + target.width, entry.left + entry.width); + const bottom = Math.min(target.top + target.height, entry.top + entry.height); + const width = right - left; + const height = bottom - top; + + if (left < right && top < bottom) + { + const targetArea = target.width * target.height; + const entryArea = entry.width * entry.height; + const intersectionArea = width * height; + const intersectionRatio = + intersectionArea / (targetArea + entryArea - intersectionArea); + + return Number(intersectionRatio.toFixed(4)); + } + + // Rectangles do not overlap, or overlap has an area of zero (edge/corner overlap) + return 0; +} + +export function centerOfRectangle( + rect: ClientRect, + left = rect.left, + top = rect.top +): Coordinates +{ + return { + x: left + rect.width * 0.5, + y: top + rect.height * 0.5 + }; +} diff --git a/entrypoints/sidepanel/utils/exportCollectionToBookmarks.ts b/entrypoints/sidepanel/utils/exportCollectionToBookmarks.ts new file mode 100644 index 0000000..20c645e --- /dev/null +++ b/entrypoints/sidepanel/utils/exportCollectionToBookmarks.ts @@ -0,0 +1,48 @@ +import { CollectionItem, TabItem } from "@/models/CollectionModels"; +import sendNotification from "@/utils/sendNotification"; +import { Bookmarks } from "wxt/browser"; +import { getCollectionTitle } from "./getCollectionTitle"; + +export default async function exportCollectionToBookmarks(collection: CollectionItem) +{ + const rootFolder: Bookmarks.BookmarkTreeNode = await browser.bookmarks.create({ + title: getCollectionTitle(collection) + }); + + for (let i = 0; i < collection.items.length; i++) + { + const item = collection.items[i]; + + if (item.type === "tab") + { + await createTabBookmark(item, rootFolder.id); + } + else + { + const groupFolder = await browser.bookmarks.create({ + parentId: rootFolder.id, + title: item.pinned + ? `📌 ${i18n.t("groups.pinned")}` : + (item.title?.trim() || `${i18n.t("groups.title")} ${i}`) + }); + + for (const tab of item.items) + await createTabBookmark(tab, groupFolder.id); + } + } + + await sendNotification({ + title: i18n.t("notifications.bookmark_saved.title"), + message: i18n.t("notifications.bookmark_saved.message"), + icon: "/notification_icons/bookmark_add.png" + }); +} + +async function createTabBookmark(tab: TabItem, parentId: string): Promise +{ + await browser.bookmarks.create({ + parentId, + title: tab.title?.trim() || tab.url, + url: tab.url + }); +}; diff --git a/entrypoints/sidepanel/utils/filterCollections.ts b/entrypoints/sidepanel/utils/filterCollections.ts new file mode 100644 index 0000000..a1fbb48 --- /dev/null +++ b/entrypoints/sidepanel/utils/filterCollections.ts @@ -0,0 +1,65 @@ +import { getCollectionTitle } from "@/entrypoints/sidepanel/utils/getCollectionTitle"; +import { CollectionItem, TabItem } from "@/models/CollectionModels"; + +export default function filterCollections( + collections: CollectionItem[] | null, + filter: CollectionFilterType +): CollectionItem[] +{ + if (!collections || collections.length < 1) + return []; + + if (!filter.query && filter.colors.length < 1) + return collections; + + const query: string = filter.query.toLocaleLowerCase(); + + return collections.filter(collection => + { + let querySatisfied: boolean = query.length < 1 || + getCollectionTitle(collection).toLocaleLowerCase().includes(query); + let colorSatisfied: boolean = filter.colors.length < 1 || + filter.colors.includes(collection.color ?? "none"); + + if (querySatisfied && colorSatisfied) + return true; + + function probeTab(tab: TabItem, query: string): boolean + { + return tab.title?.toLocaleLowerCase().includes(query) || tab.url.toLocaleLowerCase().includes(query); + } + + for (const item of collection.items) + { + if (item.type === "tab" && !querySatisfied) + { + querySatisfied = probeTab(item, query); + } + else if (item.type === "group") + { + if (item.pinned !== true) + { + if (!querySatisfied) + querySatisfied = (item.title?.toLocaleLowerCase() ?? "").includes(query); + + if (!colorSatisfied) + colorSatisfied = filter.colors.includes(item.color); + } + + if (!querySatisfied) + querySatisfied = item.items.some(i => probeTab(i, query)); + } + + if (querySatisfied && colorSatisfied) + return true; + } + + return false; + }); +} + +export type CollectionFilterType = + { + query: string; + colors: (chrome.tabGroups.ColorEnum | "none")[]; + }; diff --git a/entrypoints/sidepanel/utils/getCollectionTitle.ts b/entrypoints/sidepanel/utils/getCollectionTitle.ts new file mode 100644 index 0000000..aa55bc2 --- /dev/null +++ b/entrypoints/sidepanel/utils/getCollectionTitle.ts @@ -0,0 +1,8 @@ +import { CollectionItem } from "@/models/CollectionModels"; + +export function getCollectionTitle(collection?: CollectionItem): string +{ + return collection?.title + || new Date(collection?.timestamp ?? Date.now()) + .toLocaleDateString(browser.i18n.getUILanguage(), { year: "numeric", month: "short", day: "numeric" }); +} diff --git a/entrypoints/sidepanel/utils/getSelectedTabs.ts b/entrypoints/sidepanel/utils/getSelectedTabs.ts new file mode 100644 index 0000000..e298e55 --- /dev/null +++ b/entrypoints/sidepanel/utils/getSelectedTabs.ts @@ -0,0 +1,8 @@ +import { TabItem } from "@/models/CollectionModels"; +import { Tabs } from "wxt/browser"; + +export default async function getSelectedTabs(): Promise +{ + const tabs: Tabs.Tab[] = await browser.tabs.query({ currentWindow: true, highlighted: true }); + return tabs.filter(i => i.url).map(i => ({ type: "tab", url: i.url!, title: i.title })); +} diff --git a/entrypoints/sidepanel/utils/mergePinnedGroups.ts b/entrypoints/sidepanel/utils/mergePinnedGroups.ts new file mode 100644 index 0000000..26d554f --- /dev/null +++ b/entrypoints/sidepanel/utils/mergePinnedGroups.ts @@ -0,0 +1,27 @@ +import { CollectionItem, TabItem } from "@/models/CollectionModels"; + +export default function mergePinnedGroups(collection: CollectionItem): void +{ + const pinnedItems: TabItem[] = []; + const otherItems: CollectionItem["items"] = []; + let pinExists: boolean = false; + + collection.items.forEach(item => + { + if (item.type === "group" && item.pinned === true) + { + pinExists = true; + pinnedItems.push(...item.items); + } + else + otherItems.push(item); + }); + + if (pinnedItems.length > 0 || pinExists) + collection.items = [ + { type: "group", pinned: true, items: pinnedItems }, + ...otherItems + ]; + else + collection.items = otherItems; +} diff --git a/entrypoints/sidepanel/utils/opener.ts b/entrypoints/sidepanel/utils/opener.ts new file mode 100644 index 0000000..29fca28 --- /dev/null +++ b/entrypoints/sidepanel/utils/opener.ts @@ -0,0 +1,117 @@ +import { getCollectionTitle } from "@/entrypoints/sidepanel/utils/getCollectionTitle"; +import { CollectionItem, GroupItem, TabItem } from "@/models/CollectionModels"; +import { settings } from "@/utils/settings"; +import { Tabs, Windows } from "wxt/browser"; + +export async function openCollection(collection: CollectionItem, targetWindow?: "current" | "new" | "incognito"): Promise +{ + if (targetWindow === "incognito" && !(await browser.extension.isAllowedIncognitoAccess())) + throw new Error("The extension doesn't have incognito permission"); + + const discard: boolean = await settings.dismissOnLoad.getValue(); + + await manageWindow( + async windowId => + { + if (collection.items.some(i => i.type === "group")) + // Open tabs as regular, open groups as groups + await Promise.all(collection.items.map(async i => + { + if (i.type === "tab") + await createTab(i.url, windowId, discard); + else + await createGroup(i, windowId, discard); + })); + + else if (collection.color) + // Open collection as one big group + await createGroup({ + type: "group", + color: collection.color, + title: getCollectionTitle(collection), + items: collection.items as TabItem[] + }, windowId); + + else + // Open collection tabs as is + await Promise.all(collection.items.map(async i => + await createTab((i as TabItem).url, windowId, discard) + )); + }, + (!targetWindow || targetWindow === "current") ? + undefined : + { incognito: targetWindow === "incognito" } + ); +} + +export async function openGroup(group: GroupItem, newWindow: boolean = false): Promise +{ + await manageWindow( + windowId => createGroup(group, windowId), + newWindow ? {} : undefined + ); +} + +async function createGroup(group: GroupItem, windowId: number, discard?: boolean): Promise +{ + discard ??= await settings.dismissOnLoad.getValue(); + const tabIds: number[] = await Promise.all(group.items.map(async i => + (await createTab(i.url, windowId, discard, group.pinned)).id! + )); + + // "Pinned" group is technically not a group, so not much else to do here + // and Firefox doesn't even support tab groups + if (group.pinned === true || import.meta.env.FIREFOX) + return; + + const groupId: number = await chrome.tabs.group({ + tabIds, createProperties: { + windowId + } + }); + + await chrome.tabGroups.update(groupId, { + title: group.title, + color: group.color + }); +} + +async function manageWindow(handle: (windowId: number) => Promise, windowProps?: Windows.CreateCreateDataType): Promise +{ + const currentWindow: Windows.Window = windowProps ? + await browser.windows.create({ url: "about:blank", focused: true, ...windowProps }) : + await browser.windows.getCurrent(); + const windowId: number = currentWindow.id!; + + await handle(windowId); + + if (windowProps) + // Close "about:blank" tab + await browser.tabs.remove(currentWindow.tabs![0].id!); +} + +async function createTab(url: string, windowId: number, discard: boolean, pinned?: boolean): Promise +{ + const tab = await browser.tabs.create({ url, windowId: windowId, active: false, pinned }); + + if (discard) + discardOnLoad(tab.id!); + + return tab; +} + +function discardOnLoad(tabId: number): void +{ + const handleTabUpdated = (id: number, _: any, tab: Tabs.Tab) => + { + if (id !== tabId || !tab.url) + return; + + browser.tabs.onUpdated.removeListener(handleTabUpdated); + + if (!tab.active) + browser.tabs.discard(tabId); + }; + + browser.tabs.onUpdated.addListener(handleTabUpdated); +} diff --git a/entrypoints/sidepanel/utils/sortCollections.ts b/entrypoints/sidepanel/utils/sortCollections.ts new file mode 100644 index 0000000..5e1aa69 --- /dev/null +++ b/entrypoints/sidepanel/utils/sortCollections.ts @@ -0,0 +1,23 @@ +import { getCollectionTitle } from "@/entrypoints/sidepanel/utils/getCollectionTitle"; +import { CollectionItem } from "@/models/CollectionModels"; + +export default function sortCollections( + collections: CollectionItem[], + mode?: CollectionSortMode | null +): CollectionItem[] +{ + return sorters[mode ?? "custom"]([...collections]); +} + +export type CollectionSortMode = "ascending" | "descending" | "newest" | "oldest" | "custom"; + +const sorters: Record = +{ + ascending: i => i.sort((a, b) => getCollectionTitle(a).localeCompare(getCollectionTitle(b))), + descending: i => i.sort((a, b) => getCollectionTitle(b).localeCompare(getCollectionTitle(a))), + newest: i => i.sort((a, b) => b.timestamp - a.timestamp), + oldest: i => i.sort((a, b) => a.timestamp - b.timestamp), + custom: i => i +}; + +type CollectionSorter = (collections: CollectionItem[]) => CollectionItem[]; diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..d31604d --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,101 @@ +import css from "@eslint/css"; +import js from "@eslint/js"; +import json from "@eslint/json"; +import stylistic from "@stylistic/eslint-plugin"; +import pluginReact from "eslint-plugin-react"; +import { defineConfig } from "eslint/config"; +import globals from "globals"; +import tseslint from "typescript-eslint"; + +export default defineConfig([ + { + ignores: [".wxt/", ".output/"] + }, + { files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"], plugins: { js }, extends: ["js/recommended"] }, + { files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"], languageOptions: { globals: globals.browser } }, + { files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"], extends: [tseslint.configs.recommended] }, + { files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"], extends: [pluginReact.configs.flat.recommended] }, + { files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"], extends: [stylistic.configs.recommended] }, + { files: ["**/*.css"], plugins: { css }, language: "css/css", extends: ["css/recommended"] }, + { + files: ["**/*.{jsonc,json}"], + plugins: { json }, + language: "json/jsonc", + extends: ["json/recommended"] + }, + { + files: ["**/*.json"], + ignores: [".devcontainer/devcontainer.json"], + plugins: { json }, + language: "json/json", + extends: ["json/recommended"] + }, + { + files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"], + settings: + { + react: + { + version: "detect" + } + } + }, + { + files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"], + plugins: { + "@stylistic": stylistic + }, + rules: + { + "@stylistic/semi": ["error", "always"], + "@stylistic/block-spacing": ["warn", "always"], + "@stylistic/arrow-spacing": ["warn", { before: true, after: true }], + "@stylistic/indent": ["warn", "tab"], + "@stylistic/quotes": ["error", "double"], + "@stylistic/comma-spacing": ["warn"], + "@stylistic/comma-dangle": ["warn", "never"], + "@stylistic/no-tabs": ["warn", { allowIndentationTabs: true }], + "@stylistic/brace-style": ["warn", "allman", { allowSingleLine: true }], + "@stylistic/member-delimiter-style": ["error", { multiline: { delimiter: "semi", requireLast: true }, singleline: { delimiter: "semi", requireLast: true } }], + "@stylistic/jsx-curly-spacing": ["warn", { when: "always", children: true, attributes: true }], + "react/react-in-jsx-scope": ["off"], + "@stylistic/jsx-indent-props": ["warn", "tab"], + "@stylistic/jsx-max-props-per-line": ["off"], + "@stylistic/indent-binary-ops": ["warn", "tab"], + "@stylistic/no-multiple-empty-lines": ["warn"], + "@stylistic/operator-linebreak": ["off"], + "@stylistic/jsx-wrap-multilines": ["off"], + "@typescript-eslint/no-explicit-any": ["off"], + "@stylistic/jsx-curly-newline": ["off"], + "@stylistic/jsx-tag-spacing": + [ + "warn", + { closingSlash: "never", beforeSelfClosing: "always", afterOpening: "never" } + ], + "@stylistic/jsx-closing-bracket-location": + [ + "warn", + { nonEmpty: "tag-aligned", selfClosing: "after-props" } + ], + "@stylistic/jsx-first-prop-new-line": ["warn", "multiline"], + "@stylistic/jsx-one-expression-per-line": ["off"], + "@stylistic/jsx-closing-tag-location": ["warn"], + "@stylistic/arrow-parens": ["off"], + "@stylistic/quote-props": ["off"], + "@stylistic/multiline-ternary": ["warn"], + "@stylistic/no-trailing-spaces": ["warn"], + "@stylistic/no-mixed-spaces-and-tabs": ["warn"], + "@typescript-eslint/no-unused-vars": ["warn"], + "prefer-const": ["warn"], + "@stylistic/padded-blocks": ["warn"] + } + }, + { + files: ["**/*.css"], + plugins: { css }, + rules: + { + "css/use-baseline": ["off"] + } + } +]); diff --git a/features/collectionStorage/index.ts b/features/collectionStorage/index.ts new file mode 100644 index 0000000..2e5983d --- /dev/null +++ b/features/collectionStorage/index.ts @@ -0,0 +1,9 @@ +import { collectionStorage } from "./utils/collectionStorage"; +export * from "./utils/getCollections"; + +export { default as getCollections } from "./utils/getCollections"; +export { default as resoveConflict } from "./utils/resolveConflict"; +export { default as saveCollections } from "./utils/saveCollections"; + +export const collectionCount = collectionStorage.count; +export const graphics = collectionStorage.graphics; diff --git a/features/collectionStorage/utils/collectionStorage.ts b/features/collectionStorage/utils/collectionStorage.ts new file mode 100644 index 0000000..e6443e4 --- /dev/null +++ b/features/collectionStorage/utils/collectionStorage.ts @@ -0,0 +1,12 @@ +import { CollectionItem, GraphicsStorage } from "@/models/CollectionModels"; + +export const collectionStorage = +{ + chunkCount: storage.defineItem("sync:chunkCount", { fallback: 0 }), + syncLastUpdated: storage.defineItem("sync:lastUpdated", { fallback: 0 }), + localLastUpdated: storage.defineItem("local:lastUpdated", { fallback: 0 }), + localCollections: storage.defineItem("local:collections", { fallback: [] }), + count: storage.defineItem("local:count", { fallback: 0 }), + graphics: storage.defineItem("local:graphics", { fallback: {} }), + maxChunkCount: 12 +}; diff --git a/features/collectionStorage/utils/getChunkKeys.ts b/features/collectionStorage/utils/getChunkKeys.ts new file mode 100644 index 0000000..06222d2 --- /dev/null +++ b/features/collectionStorage/utils/getChunkKeys.ts @@ -0,0 +1,6 @@ +import { collectionStorage } from "./collectionStorage"; + +export default function getChunkKeys(start: number = 0, end: number = collectionStorage.maxChunkCount): string[] +{ + return Array.from({ length: end - start }, (_, i) => "c" + (i + start)); +} diff --git a/features/collectionStorage/utils/getCollections.ts b/features/collectionStorage/utils/getCollections.ts new file mode 100644 index 0000000..3e81897 --- /dev/null +++ b/features/collectionStorage/utils/getCollections.ts @@ -0,0 +1,36 @@ +import { CollectionItem } from "@/models/CollectionModels"; +import { collectionStorage } from "./collectionStorage"; +import getCollectionsFromCloud from "./getCollectionsFromCloud"; +import getCollectionsFromLocal from "./getCollectionsFromLocal"; +import saveCollectionsToLocal from "./saveCollectionsToLocal"; +import getLogger from "@/utils/getLogger"; + +const logger = getLogger("getCollections"); + +export default async function getCollections(): Promise<[CollectionItem[], CloudStorageIssueType | null]> +{ + const lastUpdatedLocal: number = await collectionStorage.localLastUpdated.getValue(); + const lastUpdatedSync: number = await collectionStorage.syncLastUpdated.getValue(); + + if (lastUpdatedLocal === lastUpdatedSync) + return [await getCollectionsFromLocal(), null]; + + if (lastUpdatedLocal > lastUpdatedSync) + return [await getCollectionsFromLocal(), "merge_conflict"]; + + try + { + const collections: CollectionItem[] = await getCollectionsFromCloud(); + await saveCollectionsToLocal(collections, lastUpdatedSync); + + return [collections, null]; + } + catch (ex) + { + logger("Failed to get cloud storage"); + console.error(ex); + return [await getCollectionsFromLocal(), "parse_error"]; + } +} + +export type CloudStorageIssueType = "parse_error" | "merge_conflict"; diff --git a/features/collectionStorage/utils/getCollectionsFromCloud.ts b/features/collectionStorage/utils/getCollectionsFromCloud.ts new file mode 100644 index 0000000..e04a915 --- /dev/null +++ b/features/collectionStorage/utils/getCollectionsFromCloud.ts @@ -0,0 +1,20 @@ +import { CollectionItem } from "@/models/CollectionModels"; +import { decompress } from "lzutf8"; +import { collectionStorage } from "./collectionStorage"; +import getChunkKeys from "./getChunkKeys"; +import parseCollections from "./parseCollections"; + +export default async function getCollectionsFromCloud(): Promise +{ + const chunkCount: number = await collectionStorage.chunkCount.getValue(); + + if (chunkCount < 1) + return []; + + const chunks: Record = + await browser.storage.sync.get(getChunkKeys(0, chunkCount)) as Record; + + const data: string = decompress(Object.values(chunks).join(), { inputEncoding: "StorageBinaryString" }); + + return parseCollections(data); +} diff --git a/features/collectionStorage/utils/getCollectionsFromLocal.ts b/features/collectionStorage/utils/getCollectionsFromLocal.ts new file mode 100644 index 0000000..f3d4c52 --- /dev/null +++ b/features/collectionStorage/utils/getCollectionsFromLocal.ts @@ -0,0 +1,7 @@ +import { CollectionItem } from "@/models/CollectionModels"; +import { collectionStorage } from "./collectionStorage"; + +export default async function getCollectionsFromLocal(): Promise +{ + return await collectionStorage.localCollections.getValue(); +} diff --git a/features/collectionStorage/utils/parseCollections.ts b/features/collectionStorage/utils/parseCollections.ts new file mode 100644 index 0000000..fd74191 --- /dev/null +++ b/features/collectionStorage/utils/parseCollections.ts @@ -0,0 +1,80 @@ +import { CollectionItem, GroupItem, TabItem } from "@/models/CollectionModels"; + +export default function parseCollections(data: string): CollectionItem[] +{ + if (!data) + return []; + + const collections: CollectionItem[] = []; + const lines: string[] = data.split("\n"); + + for (const line of lines) + { + if (line.startsWith("c")) + { + const collection: CollectionItem = parseCollection(line); + collections.push(collection); + } + else if (line.startsWith("\tg")) + { + const group: GroupItem = parseGroup(line); + collections[collections.length - 1].items.push(group); + } + else if (line.startsWith("\t\tt")) + { + const tab: TabItem = parseTab(line); + + const collectionIndex: number = collections.length - 1; + const groupIndex: number = collections[collectionIndex].items.length - 1; + + (collections[collectionIndex].items[groupIndex] as GroupItem).items.push(tab); + } + else if (line.startsWith("\tt")) + { + const tab: TabItem = parseTab(line); + collections[collections.length - 1].items.push(tab); + } + } + + return collections; +} + +function parseCollection(data: string): CollectionItem +{ + return { + type: "collection", + timestamp: parseInt(data.match(/(?<=^c)\d+/)!.toString()), + color: data.match(/(?<=^c\d+\/)[a-z]+/)?.toString() as chrome.tabGroups.ColorEnum, + title: data.match(/(?<=^c[\da-z/]*\|).*/)?.toString(), + items: [] + }; +} + +function parseGroup(data: string): GroupItem +{ + const isPinned: boolean = data.match(/^\tg\/p$/) !== null; + + if (isPinned) + return { + type: "group", + pinned: true, + items: [] + }; + + return { + type: "group", + pinned: false, + color: data.match(/(?<=^\tg\/)[a-z]+/)?.toString() as chrome.tabGroups.ColorEnum, + title: data.match(/(?<=^\tg\/[a-z]+\|).*$/)?.toString(), + items: [] + }; +} + +function parseTab(data: string): TabItem +{ + return { + type: "tab", + url: data.match(/(?<=^(\t){1,2}t\|).*(?=\|)/)!.toString(), + title: data.match(/(?<=^(\t){1,2}t\|.*\|).*$/)?.toString() + }; +} diff --git a/features/collectionStorage/utils/resolveConflict.ts b/features/collectionStorage/utils/resolveConflict.ts new file mode 100644 index 0000000..2b0e463 --- /dev/null +++ b/features/collectionStorage/utils/resolveConflict.ts @@ -0,0 +1,41 @@ +import { CollectionItem } from "@/models/CollectionModels"; +import getLogger from "@/utils/getLogger"; +import { collectionStorage } from "./collectionStorage"; +import getCollectionsFromCloud from "./getCollectionsFromCloud"; +import getCollectionsFromLocal from "./getCollectionsFromLocal"; +import saveCollectionsToCloud from "./saveCollectionsToCloud"; +import saveCollectionsToLocal from "./saveCollectionsToLocal"; + +const logger = getLogger("resolveConflict"); + +export default function resolveConflict(acceptSource: "local" | "sync"): Promise +{ + if (acceptSource === "local") + return replaceCloudWithLocal(); + + return replaceLocalWithCloud(); +} + +async function replaceCloudWithLocal(): Promise +{ + const collections: CollectionItem[] = await getCollectionsFromLocal(); + const lastUpdated: number = await collectionStorage.localLastUpdated.getValue(); + + await saveCollectionsToCloud(collections, lastUpdated); +} + +async function replaceLocalWithCloud(): Promise +{ + try + { + const collections: CollectionItem[] = await getCollectionsFromCloud(); + const lastUpdated: number = await collectionStorage.syncLastUpdated.getValue(); + + await saveCollectionsToLocal(collections, lastUpdated); + } + catch (ex) + { + logger("Failed to get cloud storage"); + console.error(ex); + } +} diff --git a/features/collectionStorage/utils/saveCollections.ts b/features/collectionStorage/utils/saveCollections.ts new file mode 100644 index 0000000..e266b84 --- /dev/null +++ b/features/collectionStorage/utils/saveCollections.ts @@ -0,0 +1,44 @@ +import { CollectionItem, GraphicsStorage } from "@/models/CollectionModels"; +import getLogger from "@/utils/getLogger"; +import sendNotification from "@/utils/sendNotification"; +import saveCollectionsToCloud from "./saveCollectionsToCloud"; +import saveCollectionsToLocal from "./saveCollectionsToLocal"; +import updateGraphics from "./updateGraphics"; + +const logger = getLogger("saveCollections"); + +export default async function saveCollections( + collections: CollectionItem[], + updateCloud: boolean = true, + graphicsCache?: GraphicsStorage +): Promise +{ + const timestamp: number = Date.now(); + await saveCollectionsToLocal(collections, timestamp); + + if (updateCloud) + try + { + await saveCollectionsToCloud(collections, timestamp); + } + catch (ex) + { + logger("Failed to save cloud storage"); + console.error(ex); + + if ((ex as Error).message.includes("MAX_WRITE_OPERATIONS_PER_MINUTE")) + await sendNotification({ + title: i18n.t("notifications.error_quota_exceeded.title"), + message: i18n.t("notifications.error_quota_exceeded.message"), + icon: "/notification_icons/cloud_error.png" + }); + else + await sendNotification({ + title: i18n.t("notifications.error_storage_full.title"), + message: i18n.t("notifications.error_storage_full.message"), + icon: "/notification_icons/cloud_error.png" + }); + } + + await updateGraphics(collections, graphicsCache); +}; diff --git a/features/collectionStorage/utils/saveCollectionsToCloud.ts b/features/collectionStorage/utils/saveCollectionsToCloud.ts new file mode 100644 index 0000000..392aafa --- /dev/null +++ b/features/collectionStorage/utils/saveCollectionsToCloud.ts @@ -0,0 +1,55 @@ +import { CollectionItem } from "@/models/CollectionModels"; +import { compress } from "lzutf8"; +import { WxtStorageItem } from "wxt/storage"; +import { collectionStorage } from "./collectionStorage"; +import getChunkKeys from "./getChunkKeys"; +import serializeCollections from "./serializeCollections"; + +export default async function saveCollectionsToCloud(collections: CollectionItem[], timestamp: number): Promise +{ + if (!collections || collections.length < 1) + { + await collectionStorage.chunkCount.setValue(0); + await browser.storage.sync.remove(getChunkKeys()); + return; + } + + const data: string = compress(serializeCollections(collections), { outputEncoding: "StorageBinaryString" }); + const chunks: string[] = splitIntoChunks(data); + + if (chunks.length > collectionStorage.maxChunkCount) + throw new Error("Data is too large to be stored in sync storage."); + + // Since there's a limit for cloud write operations, we need to write all chunks in one go. + const newRecords: Record = + { + [getStorageKey(collectionStorage.chunkCount)]: chunks.length, + [getStorageKey(collectionStorage.syncLastUpdated)]: timestamp + }; + + for (let i = 0; i < chunks.length; i++) + newRecords[`c${i}`] = chunks[i]; + + await browser.storage.sync.set(newRecords); + + if (chunks.length < collectionStorage.maxChunkCount) + await browser.storage.sync.remove(getChunkKeys(chunks.length)); +} + +function splitIntoChunks(data: string): string[] +{ + // QUOTA_BYTES_PER_ITEM includes length of key name, length of content and 2 more bytes (for unknown reason). + const chunkKey: string = getChunkKeys(collectionStorage.maxChunkCount - 1)[0]; + const chunkSize = (chrome.storage.sync.QUOTA_BYTES_PER_ITEM ?? 8192) - chunkKey.length - 2; + const chunks: string[] = []; + + for (let i = 0; i < data.length; i += chunkSize) + chunks.push(data.slice(i, i + chunkSize)); + + return chunks; +} + +function getStorageKey(storageItem: WxtStorageItem): string +{ + return storageItem.key.split(":")[1]; +} diff --git a/features/collectionStorage/utils/saveCollectionsToLocal.ts b/features/collectionStorage/utils/saveCollectionsToLocal.ts new file mode 100644 index 0000000..f6707bb --- /dev/null +++ b/features/collectionStorage/utils/saveCollectionsToLocal.ts @@ -0,0 +1,9 @@ +import { CollectionItem } from "@/models/CollectionModels"; +import { collectionStorage } from "./collectionStorage"; + +export default async function saveCollectionsToLocal(collections: CollectionItem[], timestamp: number): Promise +{ + await collectionStorage.localCollections.setValue(collections); + await collectionStorage.count.setValue(collections.length); + await collectionStorage.localLastUpdated.setValue(timestamp); +} diff --git a/features/collectionStorage/utils/serializeCollections.ts b/features/collectionStorage/utils/serializeCollections.ts new file mode 100644 index 0000000..76d7c8d --- /dev/null +++ b/features/collectionStorage/utils/serializeCollections.ts @@ -0,0 +1,74 @@ +import { CollectionItem, GroupItem, TabItem } from "@/models/CollectionModels"; + +export default function serializeCollections(collections: CollectionItem[]): string +{ + let data: string = ""; + + for (const collection of collections) + { + data += getCollectionString(collection); + + for (const item of collection.items) + { + if (item.type === "group") + { + data += getGroupString(item); + + for (const tab of item.items) + data += `\t${getTabString(tab)}`; + } + else if (item.type === "tab") + data += getTabString(item); + } + } + + return data; +} + +function getCollectionString(collection: CollectionItem): string +{ + let data: string = `c${collection.timestamp}`; + + if (collection.color) + data += `/${collection.color}`; + + if (collection.title) + data += `|${collection.title}`; + + data += "\n"; + + return data; +} + +function getGroupString(group: GroupItem): string +{ + let data: string = "\tg"; + + if (group.pinned === true) + data += "/p"; + else + { + data += `/${group.color}`; + + if (group.title) + data += `|${group.title}`; + } + + data += "\n"; + + return data; +} + +function getTabString(tab: TabItem): string +{ + let data: string = "\tt"; + + data += `|${tab.url}|`; + + if (tab.title) + data += tab.title; + + data += "\n"; + + return data; +} diff --git a/features/collectionStorage/utils/updateGraphics.ts b/features/collectionStorage/utils/updateGraphics.ts new file mode 100644 index 0000000..2b09ce1 --- /dev/null +++ b/features/collectionStorage/utils/updateGraphics.ts @@ -0,0 +1,51 @@ +import { CollectionItem, GraphicsItem, GraphicsStorage } from "@/models/CollectionModels"; +import { sendMessage } from "@/utils/messaging"; +import { collectionStorage } from "./collectionStorage"; + +export default async function updateGraphics( + collections: CollectionItem[], + graphicsCache?: GraphicsStorage +): Promise +{ + const localGraphics: GraphicsStorage = await collectionStorage.graphics.getValue(); + const tempGraphics: GraphicsStorage = graphicsCache || await sendMessage("getGraphicsCache", undefined); + + function getGraphics(url: string): GraphicsItem | null + { + const preview = tempGraphics[url]?.preview ?? localGraphics[url]?.preview; + const icon = tempGraphics[url]?.icon ?? localGraphics[url]?.icon; + + const graphics: GraphicsItem = {}; + + if (preview) + graphics.preview = preview; + if (icon) + graphics.icon = icon; + + return preview || icon ? graphics : null; + } + + const newGraphics: GraphicsStorage = {}; + + for (const collection of collections) + for (const item of collection.items) + { + if (item.type === "group") + for (const tab of item.items) + { + const graphics = getGraphics(tab.url); + + if (graphics) + newGraphics[tab.url] = graphics; + } + else + { + const graphics = getGraphics(item.url); + + if (graphics) + newGraphics[item.url] = graphics; + } + } + + await collectionStorage.graphics.setValue(newGraphics); +} diff --git a/features/migration/hooks/useLocalMigration.ts b/features/migration/hooks/useLocalMigration.ts new file mode 100644 index 0000000..80b60bf --- /dev/null +++ b/features/migration/hooks/useLocalMigration.ts @@ -0,0 +1,10 @@ +import migrateLocalStorage from "../utils/migrateLocalStorage"; + +export default function useLocalMigration(): void +{ + useEffect(() => + { + if (globalThis.localStorage?.getItem("sets")) + migrateLocalStorage().then(() => document.location.reload()); + }, []); +} diff --git a/features/migration/index.ts b/features/migration/index.ts new file mode 100644 index 0000000..a3b01ea --- /dev/null +++ b/features/migration/index.ts @@ -0,0 +1,2 @@ +export { default as useLocalMigration } from "./hooks/useLocalMigration"; +export { default as migrateStorage } from "./utils/migrateStorage"; diff --git a/features/migration/models/LegacyModels.ts b/features/migration/models/LegacyModels.ts new file mode 100644 index 0000000..1c91228 --- /dev/null +++ b/features/migration/models/LegacyModels.ts @@ -0,0 +1,15 @@ +export type LegacyCollection = + { + timestamp: number; + tabsCount: number; + titles: string[]; + links: string[]; + icons?: string[]; + thumbnails?: string[]; + }; + +export type LegacyGraphics = + { + pageCapture?: string; + iconUrl?: string; + }; diff --git a/features/migration/utils/migrateCollections.ts b/features/migration/utils/migrateCollections.ts new file mode 100644 index 0000000..6197794 --- /dev/null +++ b/features/migration/utils/migrateCollections.ts @@ -0,0 +1,38 @@ +import { CollectionItem, GraphicsStorage, TabItem } from "@/models/CollectionModels"; +import { LegacyCollection } from "../models/LegacyModels"; + +export default function migrateCollections(legacyCollections: LegacyCollection[]): [CollectionItem[], GraphicsStorage] +{ + const collections: CollectionItem[] = []; + const graphics: GraphicsStorage = {}; + + for (let i = 0; i < legacyCollections.length; i++) + { + const legacyCollection: LegacyCollection = legacyCollections[i]; + const items: TabItem[] = legacyCollection.links.map((url, index) => + { + const title: string | undefined = legacyCollection.titles[index]; + const icon: string | undefined = legacyCollection.icons?.[index]; + const preview: string | undefined = legacyCollection.thumbnails?.[index]; + + if (!graphics[url]) + graphics[url] = { icon, preview }; + else + graphics[url] = { icon: graphics[url].icon ?? icon, preview: graphics[url].preview ?? preview }; + + return { + type: "tab", + url, + title + }; + }); + + collections.push({ + type: "collection", + timestamp: legacyCollection.timestamp, + items + }); + } + + return [collections, graphics]; +} diff --git a/features/migration/utils/migrateLocalStorage.ts b/features/migration/utils/migrateLocalStorage.ts new file mode 100644 index 0000000..4c6a0e9 --- /dev/null +++ b/features/migration/utils/migrateLocalStorage.ts @@ -0,0 +1,18 @@ +import { getCollections } from "@/features/collectionStorage"; +import saveCollections from "@/features/collectionStorage/utils/saveCollections"; +import { LegacyCollection } from "../models/LegacyModels"; +import migrateCollections from "./migrateCollections"; + +export default async function migrateLocalStorage(): Promise +{ + // Retrieve v1 collections + const legacyCollections: LegacyCollection[] = JSON.parse(globalThis.localStorage?.getItem("sets") || "[]"); + + // Nuke localStorage + globalThis.localStorage?.clear(); + + // Migrate collections + const [resultCollections, resultGraphics] = migrateCollections(legacyCollections); + const [collections] = await getCollections(); + await saveCollections([...collections, ...resultCollections], true, resultGraphics); +} diff --git a/features/migration/utils/migrateStorage.ts b/features/migration/utils/migrateStorage.ts new file mode 100644 index 0000000..92b5b9d --- /dev/null +++ b/features/migration/utils/migrateStorage.ts @@ -0,0 +1,60 @@ +import { saveCollections } from "@/features/collectionStorage"; +import { GraphicsStorage } from "@/models/CollectionModels"; +import { settings } from "@/utils/settings"; +import { decompress } from "lzutf8"; +import { LegacyCollection, LegacyGraphics } from "../models/LegacyModels"; +import migrateCollections from "./migrateCollections"; + +export default async function migrateStorage(): Promise +{ + // Retrieve settings + const loadOnRestore: boolean | null = await storage.getItem("sync:loadOnRestore"); + const setAsideOnClick: boolean | null = await storage.getItem("sync:setAsideOnClick"); + const showDeleteDialog: boolean | null = await storage.getItem("sync:showDeleteDialog"); + const listView: boolean | null = await storage.getItem("sync:listview"); + + // Retrieve v2 collections + const legacyCollections: LegacyCollection[] = []; + Object.entries(await browser.storage.sync.get(null)).forEach(([key, value]) => + { + if (key.startsWith("set_")) + legacyCollections.push({ + ...JSON.parse(decompress(value, { inputEncoding: "StorageBinaryString" })), + timestamp: parseInt(key.substring(4)) + }); + }); + + // Retrieve v2 graphics + const v2Graphics: Record = await storage.getItem("local:thumbnails") ?? {}; + + // Nuke everything + await browser.storage.local.clear(); + await browser.storage.sync.clear(); + + // Migrate collections & graphics + const [collections] = migrateCollections(legacyCollections); + const graphics: GraphicsStorage = {}; + + for (const [key, record] of Object.entries(v2Graphics)) + { + if (!graphics[key]) + graphics[key] = { icon: record.iconUrl, preview: record.pageCapture }; + else + { + graphics[key].icon ??= record.iconUrl; + graphics[key].preview ??= record.pageCapture; + } + } + + await saveCollections(collections, true, graphics); + + // Migrate settings + if (loadOnRestore !== null) + settings.dismissOnLoad.setValue(!loadOnRestore); + if (setAsideOnClick !== null) + settings.contextAction.setValue(setAsideOnClick ? "action" : "open"); + if (showDeleteDialog !== null) + settings.deletePrompt.setValue(showDeleteDialog); + if (listView !== null) + settings.tilesView.setValue(!listView); +} diff --git a/features/v3welcome/components/WelcomeDialog.tsx b/features/v3welcome/components/WelcomeDialog.tsx new file mode 100644 index 0000000..391b9cf --- /dev/null +++ b/features/v3welcome/components/WelcomeDialog.tsx @@ -0,0 +1,68 @@ +import { useTheme } from "@/contexts/ThemeProvider"; +import { v3blogPost } from "@/data/links"; +import extLink from "@/utils/extLink"; +import * as fui from "@fluentui/react-components"; + +export default function WelcomeDialog(): React.ReactElement +{ + const { isDark } = useTheme(); + const cls = useStyles(); + + return ( + + + + + + { i18n.t("features.v3welcome.title") } + + + { i18n.t("features.v3welcome.text1") } + + + { i18n.t("features.v3welcome.text2") } + +
    + { !import.meta.env.FIREFOX && +
  • { i18n.t("features.v3welcome.list.item1") }
  • + } +
  • { i18n.t("features.v3welcome.list.item2") }
  • +
  • { i18n.t("features.v3welcome.list.item3") }
  • +
  • { i18n.t("features.v3welcome.list.item4") }
  • +
  • { i18n.t("features.v3welcome.list.item5") }
  • +
+ + { i18n.t("features.v3welcome.text3") } + + +
+ + + + + { i18n.t("features.v3welcome.actions.visit_blog") } + + + + + { i18n.t("common.actions.close") } + + + +
+
+ ); +} + +const useStyles = fui.makeStyles({ + root: + { + display: "flex", + flexFlow: "column", + gap: fui.tokens.spacingVerticalS + }, + image: + { + display: "contents" + } +}); diff --git a/features/v3welcome/hooks/useWelcomeDialog.tsx b/features/v3welcome/hooks/useWelcomeDialog.tsx new file mode 100644 index 0000000..36f7fd8 --- /dev/null +++ b/features/v3welcome/hooks/useWelcomeDialog.tsx @@ -0,0 +1,17 @@ +import { useDialog } from "@/contexts/DialogProvider"; +import WelcomeDialog from "../components/WelcomeDialog"; +import { showWelcomeDialog } from "../utils/showWelcomeDialog"; + +export default function useWelcomeDialog(): void +{ + const dialog = useDialog(); + + useEffect(() => + { + showWelcomeDialog.getValue().then(showWelcome => + { + if (showWelcome || import.meta.env.DEV) + dialog.pushCustom(, undefined, () => showWelcomeDialog.removeValue()); + }); + }, []); +} diff --git a/features/v3welcome/index.ts b/features/v3welcome/index.ts new file mode 100644 index 0000000..7f2d83f --- /dev/null +++ b/features/v3welcome/index.ts @@ -0,0 +1,2 @@ +export { default as useWelcomeDialog } from "./hooks/useWelcomeDialog"; +export { showWelcomeDialog } from "./utils/showWelcomeDialog"; diff --git a/features/v3welcome/utils/showWelcomeDialog.ts b/features/v3welcome/utils/showWelcomeDialog.ts new file mode 100644 index 0000000..064da88 --- /dev/null +++ b/features/v3welcome/utils/showWelcomeDialog.ts @@ -0,0 +1,6 @@ +export const showWelcomeDialog = storage.defineItem( + "local:showWelcome", + { + fallback: false + } +); diff --git a/hooks/useBmcStyles.ts b/hooks/useBmcStyles.ts new file mode 100644 index 0000000..2fc7a2b --- /dev/null +++ b/hooks/useBmcStyles.ts @@ -0,0 +1,13 @@ +import { makeStyles } from "@fluentui/react-components"; + +export const useBmcStyles = makeStyles({ + button: + { + backgroundColor: "#ff813f", + + "&:hover, &:hover:active": + { + backgroundColor: "#ff6b1c" + } + } +}); diff --git a/hooks/useDangerStyles.ts b/hooks/useDangerStyles.ts new file mode 100644 index 0000000..787d9ae --- /dev/null +++ b/hooks/useDangerStyles.ts @@ -0,0 +1,28 @@ +import { makeStyles, tokens } from "@fluentui/react-components"; + +export const useDangerStyles = makeStyles({ + menuItem: + { + color: tokens.colorStatusDangerForeground1 + " !important", + + "& .fui-MenuItem__icon": + { + color: tokens.colorStatusDangerForeground1 + " !important" + } + }, + buttonPrimary: + { + backgroundColor: tokens.colorStatusDangerBackground3, + color: tokens.colorNeutralForegroundStaticInverted, + + "&:hover": + { + backgroundColor: tokens.colorStatusDangerBackground3Hover, + + "&:active": + { + backgroundColor: tokens.colorStatusDangerBackground3Pressed + } + } + } +}); diff --git a/hooks/useGroupColors.ts b/hooks/useGroupColors.ts new file mode 100644 index 0000000..2ab500e --- /dev/null +++ b/hooks/useGroupColors.ts @@ -0,0 +1,49 @@ +import { makeStyles, tokens } from "@fluentui/react-components"; + +export const useGroupColors: () => Record = makeStyles({ + blue: + { + "--border": tokens.colorPaletteBlueBorderActive, + "--text": tokens.colorNeutralForegroundInverted + }, + cyan: + { + "--border": tokens.colorPaletteTealBorderActive, + "--text": tokens.colorNeutralForegroundInverted + }, + green: + { + "--border": tokens.colorPaletteGreenBorderActive, + "--text": tokens.colorNeutralForegroundInverted + }, + grey: + { + "--border": tokens.colorPalettePlatinumBorderActive, + "--text": tokens.colorNeutralForegroundInverted + }, + orange: + { + "--border": tokens.colorPalettePeachBorderActive, + "--text": tokens.colorNeutralForegroundInverted + }, + pink: + { + "--border": tokens.colorPalettePinkBorderActive, + "--text": tokens.colorNeutralForegroundInverted + }, + purple: + { + "--border": tokens.colorPalettePurpleBorderActive, + "--text": tokens.colorNeutralForegroundStaticInverted + }, + red: + { + "--border": tokens.colorPaletteRedBackground3, + "--text": tokens.colorNeutralForegroundStaticInverted + }, + yellow: + { + "--border": tokens.colorPaletteYellowBorderActive, + "--text": tokens.colorNeutralForeground1Static + } +}); diff --git a/hooks/useSettings.ts b/hooks/useSettings.ts new file mode 100644 index 0000000..3000497 --- /dev/null +++ b/hooks/useSettings.ts @@ -0,0 +1,24 @@ +import { settings } from "@/utils/settings"; + +export default function useSettings(key: K): SettingsHook +{ + const [value, setValue] = useState | null>(null); + + useEffect(() => + { + settings[key].getValue() + .then(value => setValue(value as SettingsValue)); + + const unwatch = settings[key].watch(value => setValue(value as SettingsValue)); + + return () => unwatch(); + }, [key]); + + return [value, settings[key].setValue] as SettingsHook; +} + +export type SettingsValue = + typeof settings[K] extends { fallback: infer T; } ? T : never; + +export type SettingsHook = + [SettingsValue | null, (newValue: SettingsValue) => Promise]; diff --git a/hooks/useStorageInfo.ts b/hooks/useStorageInfo.ts new file mode 100644 index 0000000..ed736a0 --- /dev/null +++ b/hooks/useStorageInfo.ts @@ -0,0 +1,27 @@ +export default function useStorageInfo(): StorageInfoHook +{ + const [bytesInUse, setBytesInUse] = useState(0); + + useEffect(() => + { + const updateValue = async () => + setBytesInUse(await browser.storage.sync.getBytesInUse()); + + updateValue(); + browser.storage.sync.onChanged.addListener(updateValue); + return () => browser.storage.sync.onChanged.removeListener(updateValue); + }, []); + + return { + bytesInUse, + storageQuota: chrome.storage.sync.QUOTA_BYTES ?? 102400, + usedStorageRatio: bytesInUse / (chrome.storage.sync.QUOTA_BYTES ?? 102400) + }; +} + +export type StorageInfoHook = + { + bytesInUse: number; + storageQuota: number; + usedStorageRatio: number; + }; diff --git a/locales/en.yml b/locales/en.yml new file mode 100644 index 0000000..50d1d00 --- /dev/null +++ b/locales/en.yml @@ -0,0 +1,245 @@ +manifest: + name: "Tabs aside" + description: "Save and organize your tabs for later. Pick up where you left off" + author: "Eugene Fox" + +shortcuts: + toggle_sidebar: "Open collection list" + set_aside: "Set tabs aside" + save_tabs: "Save tabs without closing" + +common: + actions: + cancel: "Cancel" + save: "Save" + close: "Close" + delete: "Delete" + reset_filters: "Reset filters" + cta: + feedback: "Leave feedback" + sponsor: "Buy me a coffee" + tooltips: + more: "More" + delete_prompt: "Are you sure? This action cannot be undone." + +features: + v3welcome: + title: "Welcome to Tabs aside 3.0" + text1: "We are happy to announce our new major update for Tabs aside extension!" + text2: "This update brings a brand new UI, and a lot of new features, including:" + list: + item1: "Tab groups support" + item2: "Collection customization" + item3: "Drag and drop reordering and organizing" + item4: "Manual collection creation from scratch" + item5: "And more!" + text3: "Visit our dev blog to learn more about this update and all of its features!" + actions: + visit_blog: "Read dev blog" + +notifications: + tabs_saved: + title: "New collection created" + message: "Your tabs have been saved to a new collection" + error_quota_exceeded: + title: "Maximum cloud write operations exceeded" + message: "We saved your tabs in local storage. You will have to manually update your cloud storage" + error_storage_full: + title: "Your cloud storage is full" + message: "We saved your tabs in local storage. Please clear some space in your cloud storage" + bookmark_saved: + title: "Exported to bookmarks" + message: "Your collection has been exported to bookmarks" + partial_save: + title: "Some tabs couldn't be saved" + message: "Some of the tabs were system tabs we could not access. They were skipped" + +actions: + save: + all: "Save all tabs" + selected: "Save selected tabs" + set_aside: + all: "Set all tabs aside" + selected: "Set selected tabs aside" + show_collections: "Show collections" + +options_page: + title: "Settings" + general: + title: "General" + options: + always_show_toolbars: "Always show toolbars" + include_pinned: "Include pinned tabs when saving all tabs" + show_delete_prompt: "Ask for confirmation when deleting an item" + show_badge: "Show counter badge" + show_notification: "Show notification when saving tabs using context menu" + unload_tabs: "Do not load tabs after opening" + list_locations: + title: "Open collection list in:" + options: + sidebar: "Sidebar" + popup: "Popup" + tab: "Separate tab" + pinned: "Separate pinned tab" + icon_action: + title: "When clicking on the extension icon:" + options: + action: "Perform default save action" + context: "Show context menu" + open: "Open collection list" + change_shortcuts: "Change extension shortcuts" + actions: + title: "Default actions" + options: + save_actions: + title: "Default action when saving tabs" + options: + set_aside: "Save and close tabs" + save: "Save tabs without closing" + restore_actions: + title: "Default action when opening collections" + options: + open: "Just open the tabs" + restore: "Open tabs and remove the collection" + storage: + title: "Storage" + capacity: + title: "Cloud storage capacity" + description: "$1 of $2 KiB" + import: "Import data" + export: "Export data" + import_results: + success: "Data successfully imported" + error: "Provided file appears to be corrupted. Nothing was imported" + import_prompt: + title: "Import data" + warning_title: "This is an irreversible action" + warning_text: "This will overwrite all your data. Make sure you picked a correct file, otherwise data corruption or loss may occur. It is recommended to export data first." + proceed: "Pick a file" + about: + title: "About" + developed_by: "Developed by Eugene Fox" + licensed_under: "Licensed under" + mit_license: "MIT License" + translation_cta: + text: "Found a typo or want a translation for your language?" + button: "Get started here" + links: + website: "My website" + source: "Source code" + changelog: "Changelog" + +collections: + empty: "This collection is empty" + tabs_count: "$1 tabs" + actions: + open: "Open all" + restore: "Restore all" + new_window: "Open all in new window" + incognito: + edge: "Open all in new InPrivate window" + firefox: "Open all in new private window" + chrome: "Open all in incognito window" + incognito_check: + title: "Permissions required" + message: + edge: + p1: "The extension needs permission to open tabs in InPrivate window" + p2: "To do this, click \"Settings\" and then check \"Allow in InPrivate\" option" + firefox: + p1: "The extension needs permission to open tabs in private window" + p2: "To do this, click \"Settings\", go to \"Details\" and set \"Run in Private Windows\" to \"Allow\"" + chrome: + p1: "The extension needs permission to open tabs in incognito window" + p2: "To do this, click \"Settings\" and then check \"Allow in Incognito\" option" + action: "Settings" + menu: + delete: "Delete collection" + add_selected: "Add selected tabs" + add_group: "Add empty group" + add_pinned: "Add pinned group" + export_bookmarks: "Export to bookmarks" + edit: "Edit collection" + +groups: + title: "Group" + pinned: "Pinned" + open: "Open all" + empty: "This group is empty" + menu: + new_window: "Open in new window" + add_selected: "Add selected tabs" + edit: "Edit group" + ungroup: "Ungroup" + delete: "Delete group" + +tabs: + delete: "Delete tab" + +colors: + none: "No color" + any: "Any color" + grey: "Grey" + blue: "Blue" + red: "Red" + yellow: "Yellow" + green: "Green" + pink: "Pink" + purple: "Purple" + cyan: "Cyan" + orange: "Orange" + +dialogs: + edit: + title: + edit_collection: "Edit collection" + edit_group: "Edit group" + new_group: "New group" + new_collection: "New collection" + collection_title: "Title" + color: "Color" + +main: + header: + create_collection: "Create new collection" + menu: + tiles_view: "Tiles view" + changelog: "What's new?" + list: + searchbar: + title: "Search" + filter: "Filter" + sort: + title: "Sort" + options: + newest: "Newest first" + oldest: "Oldest first" + ascending: "From A to Z" + descending: "From Z to A" + custom: "Custom" + empty: + title: "Nothing to show here yet" + message: "Set aside your current tabs, or create a new collection" + empty_search: + title: "Couldn't find anything" + message: "Try to change your search query" + +cta_message: + title: "Like this extension?" + message: "Consider supporting the author with a donation, or" + feedback: "leaving a feedback" + +storage_full_message: + title: "Your cloud storage is almost full ($1%)" + message: "You can free up some space by deleting unused collections." + +parse_error_message: + title: "We couldn't get collections from your cloud storage." + message: "Your cloud storage appears to be corrupted. You can fix it by replacing it with your local copy." + action: "Fix with local copy" + +merge_conflict_message: + title: "Your local and cloud storages have conflicting changes." + message: "To fix this, you can either upload your local copy to the cloud, or accept the cloud changes." + accept_local: "Replace with local" + accept_cloud: "Accept cloud changes" diff --git a/locales/ru.yml b/locales/ru.yml new file mode 100644 index 0000000..5c471a2 --- /dev/null +++ b/locales/ru.yml @@ -0,0 +1,245 @@ +manifest: + name: "ĐžŅ‚ĐģĐžĐļĐĩĐŊĐŊŅ‹Đĩ вĐēĐģадĐēи" + description: "ĐžŅ‚ĐēĐģĐ°Đ´Ņ‹Đ˛Đ°ĐšŅ‚Đĩ и ĐžŅ€ĐŗĐ°ĐŊĐ¸ĐˇŅƒĐšŅ‚Đĩ ŅĐ˛ĐžĐ¸ вĐēĐģадĐēи. ĐŸŅ€ĐžĐ´ĐžĐģĐļĐ°ĐšŅ‚Đĩ ҁ Ņ‚ĐžĐŗĐž ĐŧĐĩŅŅ‚Đ°, ĐŗĐ´Đĩ ĐžŅŅ‚Đ°ĐŊОвиĐģĐ¸ŅŅŒ" + author: "Đ•Đ˛ĐŗĐĩĐŊиК Đ›Đ¸Ņ" + +shortcuts: + toggle_sidebar: "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ ҁĐŋĐ¸ŅĐžĐē ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Đš" + set_aside: "ĐžŅ‚ĐģĐžĐļĐ¸Ņ‚ŅŒ вĐēĐģадĐēи" + save_tabs: "ĐĄĐžŅ…Ņ€Đ°ĐŊĐ¸Ņ‚ŅŒ вĐēĐģадĐēи" + +common: + actions: + cancel: "ĐžŅ‚ĐŧĐĩĐŊа" + save: "ĐĄĐžŅ…Ņ€Đ°ĐŊĐ¸Ņ‚ŅŒ" + close: "ЗаĐēŅ€Ņ‹Ņ‚ŅŒ" + delete: "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ" + reset_filters: "ĐĄĐąŅ€ĐžŅĐ¸Ņ‚ŅŒ Ņ„Đ¸ĐģŅŒŅ‚Ņ€Ņ‹" + cta: + feedback: "ĐžŅŅ‚Đ°Đ˛Đ¸Ņ‚ŅŒ ĐžŅ‚ĐˇŅ‹Đ˛" + sponsor: "ПоддĐĩŅ€ĐļĐ°Ņ‚ŅŒ" + tooltips: + more: "Đ•Ņ‰Ņ‘" + delete_prompt: "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹? Đ­Ņ‚Đž Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ ĐŊĐĩĐģŅŒĐˇŅ ĐžŅ‚ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ." + +features: + v3welcome: + title: "Đ”ĐžĐąŅ€Đž ĐŋĐžĐļаĐģĐžĐ˛Đ°Ņ‚ŅŒ в ĐžŅ‚ĐģĐžĐļĐĩĐŊĐŊŅ‹Đĩ вĐēĐģадĐēи 3.0" + text1: "ĐœŅ‹ Ņ€Đ°Đ´Ņ‹ ĐŋŅ€ĐĩĐ´ŅŅ‚Đ°Đ˛Đ¸Ņ‚ŅŒ ĐŊОвОĐĩ йОĐģŅŒŅˆĐžĐĩ ОйĐŊОвĐģĐĩĐŊиĐĩ Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐ¸Ņ!" + text2: "Đ­Ņ‚Đž ОйĐŊОвĐģĐĩĐŊиĐĩ вĐēĐģŅŽŅ‡Đ°ĐĩŅ‚ ŅĐžĐ˛ĐĩŅ€ŅˆĐĩĐŊĐŊĐž ĐŊĐžĐ˛Ņ‹Đš иĐŊŅ‚ĐĩҀ҄ĐĩĐšŅ и ĐŧĐŊĐžĐļĐĩŅŅ‚Đ˛Đž ĐŊĐžĐ˛Ņ‹Ņ… Ņ„ŅƒĐŊĐēŅ†Đ¸Đš, Ņ‚Đ°ĐēĐ¸Ņ… ĐēаĐē:" + list: + item1: "ПоддĐĩŅ€ĐļĐēа ĐŗŅ€ŅƒĐŋĐŋĐ¸Ņ€ĐžĐ˛Đēи вĐēĐģадОĐē" + item2: "ПĐĩŅ€ŅĐžĐŊаĐģĐ¸ĐˇĐ°Ņ†Đ¸Ņ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Đš" + item3: "ПĐĩŅ€ĐĩŅ‚Đ°ŅĐēиваĐŊиĐĩ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Đš и ŅĐģĐĩĐŧĐĩĐŊŅ‚ĐžĐ˛" + item4: "ХОСдаĐŊиĐĩ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Đš ҁ ĐŊ҃ĐģŅ" + item5: "И ĐŧĐŊĐžĐŗĐžĐĩ Đ´Ņ€ŅƒĐŗĐžĐĩ!" + text3: "ĐŸĐžŅĐĩŅ‚Đ¸Ņ‚Đĩ ĐąĐģĐžĐŗ Ņ€Đ°ĐˇŅ€Đ°ĐąĐžŅ‚Ņ‡Đ¸Đēа (Ņ‚ĐžĐģҌĐēĐž ĐŊа аĐŊĐŗĐģĐ¸ĐšŅĐēĐžĐŧ), Ņ‡Ņ‚ĐžĐąŅ‹ ŅƒĐˇĐŊĐ°Ņ‚ŅŒ йОĐģҌ҈Đĩ Ой ŅŅ‚ĐžĐŧ ОйĐŊОвĐģĐĩĐŊии и Đ˛ŅĐĩŅ… ĐĩĐŗĐž Ņ„ŅƒĐŊĐēŅ†Đ¸ŅŅ…!" + actions: + visit_blog: "Đ§Đ¸Ņ‚Đ°Ņ‚ŅŒ ĐąĐģĐžĐŗ" + +notifications: + tabs_saved: + title: "ХОСдаĐŊа ĐŊĐžĐ˛Đ°Ņ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Ņ" + message: "Đ’Đ°ŅˆĐ¸ вĐēĐģадĐēи ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊŅ‹ в ĐŊĐžĐ˛ŅƒŅŽ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸ŅŽ" + error_quota_exceeded: + title: "ĐŸŅ€ĐĩĐ˛Ņ‹ŅˆĐĩĐŊ ĐģиĐŧĐ¸Ņ‚ ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸Đš СаĐŋĐ¸ŅĐ¸ в ОйĐģаĐēĐž" + message: "ĐœŅ‹ ŅĐžŅ…Ņ€Đ°ĐŊиĐģи Đ˛Đ°ŅˆĐ¸ вĐēĐģадĐēи в ĐģĐžĐēаĐģҌĐŊĐžĐĩ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đĩ. ВаĐŧ ĐŊ҃ĐļĐŊĐž ĐąŅƒĐ´ĐĩŅ‚ Đ˛Ņ€ŅƒŅ‡ĐŊŅƒŅŽ ОйĐŊĐžĐ˛Đ¸Ņ‚ŅŒ ОйĐģĐ°Ņ‡ĐŊĐžĐĩ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đĩ" + error_storage_full: + title: "ОбĐģĐ°Ņ‡ĐŊĐžĐĩ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đĩ СаĐŋĐžĐģĐŊĐĩĐŊĐž" + message: "ĐœŅ‹ ŅĐžŅ…Ņ€Đ°ĐŊиĐģи Đ˛Đ°ŅˆĐ¸ вĐēĐģадĐēи в ĐģĐžĐēаĐģҌĐŊĐžĐĩ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đĩ. ПоĐļаĐģŅƒĐšŅŅ‚Đ°, ĐžŅĐ˛ĐžĐąĐžĐ´Đ¸Ņ‚Đĩ ĐŧĐĩŅŅ‚Đž в ОйĐģĐ°Ņ‡ĐŊĐžĐŧ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đĩ" + bookmark_saved: + title: "Đ­ĐēҁĐŋĐžŅ€Ņ‚Đ¸Ņ€ĐžĐ˛Đ°ĐŊĐž в СаĐēĐģадĐēи" + message: "Đ’Đ°ŅˆĐ° ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Ņ ŅĐēҁĐŋĐžŅ€Ņ‚Đ¸Ņ€ĐžĐ˛Đ°ĐŊа в СаĐēĐģадĐēи" + partial_save: + title: "НĐĩĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ вĐēĐģадĐēи ĐŊĐĩ ĐąŅ‹Đģи ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊŅ‹" + message: "НĐĩĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ иС вĐēĐģадОĐē ŅĐ˛ĐģŅŅŽŅ‚ŅŅ ŅĐ¸ŅŅ‚ĐĩĐŧĐŊŅ‹Đŧи и ĐŊĐĩ ĐŧĐžĐŗŅƒŅ‚ ĐąŅ‹Ņ‚ŅŒ ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊŅ‹" + +actions: + save: + all: "ĐĄĐžŅ…Ņ€Đ°ĐŊĐ¸Ņ‚ŅŒ Đ˛ŅĐĩ вĐēĐģадĐēи" + selected: "ĐĄĐžŅ…Ņ€Đ°ĐŊĐ¸Ņ‚ŅŒ Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ вĐēĐģадĐēи" + set_aside: + all: "ĐžŅ‚ĐģĐžĐļĐ¸Ņ‚ŅŒ Đ˛ŅĐĩ вĐēĐģадĐēи" + selected: "ĐžŅ‚ĐģĐžĐļĐ¸Ņ‚ŅŒ Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ вĐēĐģадĐēи" + show_collections: "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ҁĐŋĐ¸ŅĐžĐē ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Đš" + +options_page: + title: "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи" + general: + title: "ĐžĐąŅ‰Đ¸Đĩ" + options: + always_show_toolbars: "Đ’ŅĐĩĐŗĐ´Đ° ĐŋĐžĐēĐ°ĐˇŅ‹Đ˛Đ°Ņ‚ŅŒ ĐŋаĐŊĐĩĐģи Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đš" + include_pinned: "ĐĄĐžŅ…Ņ€Đ°ĐŊŅŅ‚ŅŒ СаĐēŅ€ĐĩĐŋĐģĐĩĐŊĐŊŅ‹Đĩ вĐēĐģадĐēи ĐŋŅ€Đ¸ ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊии Đ˛ŅĐĩŅ… вĐēĐģадОĐē" + show_delete_prompt: "ĐĄĐŋŅ€Đ°ŅˆĐ¸Đ˛Đ°Ņ‚ŅŒ ĐŋĐžĐ´Ņ‚Đ˛ĐĩŅ€ĐļĐ´ĐĩĐŊиĐĩ ĐŋŅ€Đ¸ ŅƒĐ´Đ°ĐģĐĩĐŊии ŅĐģĐĩĐŧĐĩĐŊŅ‚ĐžĐ˛" + show_badge: "ПоĐēĐ°ĐˇŅ‹Đ˛Đ°Ņ‚ŅŒ ҁ҇ĐĩŅ‚Ņ‡Đ¸Đē" + show_notification: "ПоĐēĐ°ĐˇŅ‹Đ˛Đ°Ņ‚ŅŒ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиĐĩ ĐŋŅ€Đ¸ ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊии ҇ĐĩŅ€ĐĩС ĐēĐžĐŊŅ‚ĐĩĐēҁ҂ĐŊĐžĐĩ ĐŧĐĩĐŊŅŽ" + unload_tabs: "НĐĩ ĐˇĐ°ĐŗŅ€ŅƒĐļĐ°Ņ‚ŅŒ вĐēĐģадĐēи ĐŋĐžŅĐģĐĩ ĐžŅ‚ĐēŅ€Ņ‹Ņ‚Đ¸Ņ" + list_locations: + title: "ĐžŅ‚ĐēŅ€Ņ‹Đ˛Đ°Ņ‚ŅŒ ҁĐŋĐ¸ŅĐžĐē ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Đš в:" + options: + sidebar: "БоĐēОвОК ĐŋаĐŊĐĩĐģи" + popup: "Đ’ŅĐŋĐģŅ‹Đ˛Đ°ŅŽŅ‰ĐĩĐŧ ĐžĐēĐŊĐĩ" + tab: "ĐžŅ‚Đ´ĐĩĐģҌĐŊОК вĐēĐģадĐēĐĩ" + pinned: "ĐžŅ‚Đ´ĐĩĐģҌĐŊОК СаĐēŅ€ĐĩĐŋĐģĐĩĐŊĐŊОК вĐēĐģадĐēĐĩ" + icon_action: + title: "ĐŸŅ€Đ¸ ĐŊаĐļĐ°Ņ‚Đ¸Đ¸ ĐŊа иĐēĐžĐŊĐē҃ Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐ¸Ņ:" + options: + action: "Đ’Ņ‹ĐŋĐžĐģĐŊĐ¸Ņ‚ŅŒ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ ĐŋĐž ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ" + context: "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐēĐžĐŊŅ‚ĐĩĐēҁ҂ĐŊĐžĐĩ ĐŧĐĩĐŊŅŽ" + open: "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ ҁĐŋĐ¸ŅĐžĐē ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Đš" + change_shortcuts: "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŗĐžŅ€ŅŅ‡Đ¸Đĩ ĐēĐģĐ°Đ˛Đ¸ŅˆĐ¸" + actions: + title: "ДĐĩĐšŅŅ‚Đ˛Đ¸Ņ" + options: + save_actions: + title: "ДĐĩĐšŅŅ‚Đ˛Đ¸Đĩ ĐŋĐž ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ ĐŋŅ€Đ¸ ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊии вĐēĐģадОĐē" + options: + set_aside: "ĐĄĐžŅ…Ņ€Đ°ĐŊĐ¸Ņ‚ŅŒ и СаĐēŅ€Ņ‹Ņ‚ŅŒ вĐēĐģадĐēи" + save: "ĐĄĐžŅ…Ņ€Đ°ĐŊĐ¸Ņ‚ŅŒ вĐēĐģадĐēи, ĐŊĐĩ СаĐēŅ€Ņ‹Đ˛Đ°Ņ Đ¸Ņ…" + restore_actions: + title: "ДĐĩĐšŅŅ‚Đ˛Đ¸Đĩ ĐŋĐž ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ ĐŋŅ€Đ¸ ĐžŅ‚ĐēŅ€Ņ‹Ņ‚Đ¸Đ¸ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Đš" + options: + open: "ĐŸŅ€ĐžŅŅ‚Đž ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ вĐēĐģадĐēи" + restore: "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ вĐēĐģадĐēи и ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸ŅŽ" + storage: + title: "ĐĨŅ€Đ°ĐŊиĐģĐ¸Ņ‰Đĩ" + capacity: + title: "ĐžĐąŅŠŅ‘Đŧ ОйĐģĐ°Ņ‡ĐŊĐžĐŗĐž Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ°" + description: "$1 иС $2 КиБ" + import: "ИĐŧĐŋĐžŅ€Ņ‚ даĐŊĐŊҋ҅" + export: "Đ­ĐēҁĐŋĐžŅ€Ņ‚ даĐŊĐŊҋ҅" + import_results: + success: "ДаĐŊĐŊŅ‹Đĩ ҃ҁĐŋĐĩ҈ĐŊĐž иĐŧĐŋĐžŅ€Ņ‚Đ¸Ņ€ĐžĐ˛Đ°ĐŊŅ‹" + error: "ĐŸĐžŅ…ĐžĐļĐĩ, Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đš Ņ„Đ°ĐšĐģ ĐŋĐžĐ˛Ņ€ĐĩĐļĐ´ĐĩĐŊ. ĐĐ¸Ņ‡ĐĩĐŗĐž ĐŊĐĩ ĐąŅ‹ĐģĐž иĐŧĐŋĐžŅ€Ņ‚Đ¸Ņ€ĐžĐ˛Đ°ĐŊĐž" + import_prompt: + title: "ИĐŧĐŋĐžŅ€Ņ‚ даĐŊĐŊҋ҅" + warning_title: "Đ­Ņ‚Đž ĐŊĐĩĐžĐąŅ€Đ°Ņ‚Đ¸ĐŧĐžĐĩ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ!" + warning_text: "ОĐŊĐž ĐŋĐĩŅ€ĐĩСаĐŋĐ¸ŅˆĐĩŅ‚ Đ˛ŅĐĩ Đ˛Đ°ŅˆĐ¸ даĐŊĐŊŅ‹Đĩ. ĐŖĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž Đ˛Ņ‹ Đ˛Ņ‹ĐąŅ€Đ°Đģи ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊŅ‹Đš Ņ„Đ°ĐšĐģ, иĐŊĐ°Ņ‡Đĩ ŅŅ‚Đž ĐŧĐžĐļĐĩŅ‚ ĐŋŅ€Đ¸Đ˛ĐĩŅŅ‚Đ¸ Đē ĐŋĐžĐ˛Ņ€ĐĩĐļĐ´ĐĩĐŊĐ¸ŅŽ иĐģи ĐŋĐžŅ‚ĐĩŅ€Đĩ даĐŊĐŊҋ҅. Đ ĐĩĐēĐžĐŧĐĩĐŊĐ´ŅƒĐĩŅ‚ŅŅ ҁĐŊĐ°Ņ‡Đ°Đģа ŅĐēҁĐŋĐžŅ€Ņ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ даĐŊĐŊŅ‹Đĩ." + proceed: "Đ’Ņ‹ĐąŅ€Đ°Ņ‚ŅŒ Ņ„Đ°ĐšĐģ" + about: + title: "О Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊии" + developed_by: "Đ Đ°ĐˇŅ€Đ°ĐąĐžŅ‚Ņ‡Đ¸Đē: Đ•Đ˛ĐŗĐĩĐŊиК Đ›Đ¸Ņ" + licensed_under: "" + mit_license: "Đ›Đ¸Ņ†ĐĩĐŊĐˇĐ¸Ņ MIT" + translation_cta: + text: "ĐĐ°ŅˆĐģи ĐžĐŋĐĩŅ‡Đ°Ņ‚Đē҃ иĐģи Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐŋĐĩŅ€ĐĩвОд ĐŊа Đ˛Đ°Ņˆ ŅĐˇŅ‹Đē?" + button: "ĐĐ°Ņ‡ĐŊĐ¸Ņ‚Đĩ СдĐĩҁҌ" + links: + website: "Мой вĐĩĐą-ŅĐ°ĐšŅ‚" + source: "Đ˜ŅŅ…ĐžĐ´ĐŊŅ‹Đš ĐēОд" + changelog: "ĐĄĐŋĐ¸ŅĐžĐē иСĐŧĐĩĐŊĐĩĐŊиК" + +collections: + empty: "Đ­Ņ‚Đ° ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Ņ ĐŋŅƒŅŅ‚Đ°" + tabs_count: "ВĐēĐģадОĐē: $1" + actions: + open: "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ Đ˛ŅĐĩ" + restore: "Đ’ĐžŅŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ Đ˛ŅĐĩ" + new_window: "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ в ĐŊОвОĐŧ ĐžĐēĐŊĐĩ" + incognito: + edge: "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ в ĐžĐēĐŊĐĩ InPrivate" + firefox: "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ в ĐŊОвОĐŧ ĐŋŅ€Đ¸Đ˛Đ°Ņ‚ĐŊĐžĐŧ ĐžĐēĐŊĐĩ" + chrome: "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ в Ņ€ĐĩĐļиĐŧĐĩ иĐŊĐēĐžĐŗĐŊĐ¸Ņ‚Đž" + incognito_check: + title: "ĐĸŅ€ĐĩĐąŅƒĐĩŅ‚ŅŅ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ" + message: + edge: + p1: "Đ Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐ¸ŅŽ ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐž Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊĐžĐĩ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ Ņ‡Ņ‚ĐžĐąŅ‹ ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ вĐēĐģадĐēи в Ņ€ĐĩĐļиĐŧĐĩ InPrivate" + p2: "ДĐģŅ ŅŅ‚ĐžĐŗĐž ĐŊаĐļĐŧĐ¸Ņ‚Đĩ \"ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи\" и ĐˇĐ°Ņ‚ĐĩĐŧ ĐžŅ‚ĐŧĐĩŅ‚ŅŒŅ‚Đĩ ĐžĐŋŅ†Đ¸ŅŽ \"Đ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒ в Ņ€ĐĩĐļиĐŧĐĩ InPrivate\"" + firefox: + p1: "Đ Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐ¸ŅŽ ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐž Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊĐžĐĩ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ Ņ‡Ņ‚ĐžĐąŅ‹ ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ вĐēĐģадĐēи в ĐŋŅ€Đ¸Đ˛Đ°Ņ‚ĐŊĐžĐŧ ĐžĐēĐŊĐĩ" + p2: "ДĐģŅ ŅŅ‚ĐžĐŗĐž ĐŊаĐļĐŧĐ¸Ņ‚Đĩ \"ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи\", ĐŋĐĩŅ€ĐĩĐšĐ´Đ¸Ņ‚Đĩ в \"ĐŸĐžĐ´Ņ€ĐžĐąĐŊĐžŅŅ‚Đ¸\" и Ņ€Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚Đĩ \"ЗаĐŋ҃ҁĐē в ĐŋŅ€Đ¸Đ˛Đ°Ņ‚ĐŊҋ҅ ĐžĐēĐŊĐ°Ņ…\"" + chrome: + p1: "Đ Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐ¸ŅŽ ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐž Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊĐžĐĩ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ Ņ‡Ņ‚ĐžĐąŅ‹ ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ вĐēĐģадĐēи в Ņ€ĐĩĐļиĐŧĐĩ иĐŊĐēĐžĐŗĐŊĐ¸Ņ‚Đž" + p2: "ДĐģŅ ŅŅ‚ĐžĐŗĐž ĐŊаĐļĐŧĐ¸Ņ‚Đĩ \"ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи\" и ĐžŅ‚ĐŧĐĩŅ‚ŅŒŅ‚Đĩ ĐžĐŋŅ†Đ¸ŅŽ \"Đ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩ в Ņ€ĐĩĐļиĐŧĐĩ иĐŊĐēĐžĐŗĐŊĐ¸Ņ‚Đž\"" + action: "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи" + menu: + delete: "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸ŅŽ" + add_selected: "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ вĐēĐģадĐēи" + add_group: "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐŋŅƒŅŅ‚ŅƒŅŽ ĐŗŅ€ŅƒĐŋĐŋ҃" + add_pinned: "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ СаĐēŅ€ĐĩĐŋĐģĐĩĐŊĐŊŅƒŅŽ ĐŗŅ€ŅƒĐŋĐŋ҃" + export_bookmarks: "Đ­ĐēҁĐŋĐžŅ€Ņ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ в СаĐēĐģадĐēи" + edit: "Đ ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸ŅŽ" + +groups: + title: "Đ“Ņ€ŅƒĐŋĐŋа" + pinned: "ЗаĐēŅ€ĐĩĐŋĐģĐĩĐŊĐŊŅ‹Đĩ" + open: "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ Đ˛ŅĐĩ" + empty: "Đ­Ņ‚Đ° ĐŗŅ€ŅƒĐŋĐŋа ĐŋŅƒŅŅ‚Đ°" + menu: + new_window: "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ в ĐŊОвОĐŧ ĐžĐēĐŊĐĩ" + add_selected: "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ вĐēĐģадĐēи" + edit: "Đ ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐŗŅ€ŅƒĐŋĐŋ҃" + ungroup: "Đ Đ°ĐˇĐŗŅ€ŅƒĐŋĐŋĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ" + delete: "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐŗŅ€ŅƒĐŋĐŋ҃" + +tabs: + delete: "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ вĐēĐģадĐē҃" + +colors: + none: "БĐĩС Ņ†Đ˛ĐĩŅ‚Đ°" + any: "Đ›ŅŽĐąĐžĐš Ņ†Đ˛ĐĩŅ‚" + grey: "ĐĄĐĩŅ€Ņ‹Đš" + blue: "ХиĐŊиК" + red: "ĐšŅ€Đ°ŅĐŊŅ‹Đš" + yellow: "Đ–Ņ‘ĐģŅ‚Ņ‹Đš" + green: "ЗĐĩĐģŅ‘ĐŊŅ‹Đš" + pink: "Đ ĐžĐˇĐžĐ˛Ņ‹Đš" + purple: "ФиОĐģĐĩŅ‚ĐžĐ˛Ņ‹Đš" + cyan: "ГоĐģŅƒĐąĐžĐš" + orange: "ĐžŅ€Đ°ĐŊĐļĐĩĐ˛Ņ‹Đš" + +dialogs: + edit: + title: + edit_collection: "Đ ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸ŅŽ" + edit_group: "Đ ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐŗŅ€ŅƒĐŋĐŋ҃" + new_group: "ĐĐžĐ˛Đ°Ņ ĐŗŅ€ŅƒĐŋĐŋа" + new_collection: "ĐĐžĐ˛Đ°Ņ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Ņ" + collection_title: "НазваĐŊиĐĩ" + color: "ĐĻвĐĩŅ‚" + +main: + header: + create_collection: "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ ĐŊĐžĐ˛ŅƒŅŽ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸ŅŽ" + menu: + tiles_view: "ПĐģĐ¸Ņ‚Đēи" + changelog: "Đ§Ņ‚Đž ĐŊĐžĐ˛ĐžĐŗĐž?" + list: + searchbar: + title: "ĐŸĐžĐ¸ŅĐē" + filter: "ФиĐģŅŒŅ‚Ņ€" + sort: + title: "ĐĄĐžŅ€Ņ‚Đ¸Ņ€ĐžĐ˛Đēа" + options: + newest: "ĐĄĐŊĐ°Ņ‡Đ°Đģа ĐŊĐžĐ˛Ņ‹Đĩ" + oldest: "ĐĄĐŊĐ°Ņ‡Đ°Đģа ŅŅ‚Đ°Ņ€Ņ‹Đĩ" + ascending: "ĐžŅ‚ А Đ´Đž Đ¯" + descending: "ĐžŅ‚ Đ¯ Đ´Đž А" + custom: "ĐŸŅ€ĐžĐ¸ĐˇĐ˛ĐžĐģҌĐŊĐ°Ņ" + empty: + title: "ПоĐēа Ņ‡Ņ‚Đž СдĐĩҁҌ ĐŊĐ¸Ņ‡ĐĩĐŗĐž ĐŊĐĩŅ‚" + message: "ĐžŅ‚ĐģĐžĐļĐ¸Ņ‚Đĩ Ņ‚ĐĩĐēŅƒŅ‰Đ¸Đĩ вĐēĐģадĐēи иĐģи ŅĐžĐˇĐ´Đ°ĐšŅ‚Đĩ ĐŊĐžĐ˛ŅƒŅŽ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸ŅŽ" + empty_search: + title: "ĐĐ¸Ņ‡ĐĩĐŗĐž ĐŊĐĩ ĐŊаКдĐĩĐŊĐž" + message: "ПоĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ иСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŋĐžĐ¸ŅĐēĐžĐ˛Ņ‹Đš СаĐŋŅ€ĐžŅ" + +cta_message: + title: "ĐŅ€Đ°Đ˛Đ¸Ņ‚ŅŅ Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊиĐĩ?" + message: "ПоддĐĩŅ€ĐļĐ¸Ņ‚Đĩ Đ°Đ˛Ņ‚ĐžŅ€Đ° ĐŋĐžĐļĐĩŅ€Ņ‚Đ˛ĐžĐ˛Đ°ĐŊиĐĩĐŧ иĐģи" + feedback: "ĐžŅŅ‚Đ°Đ˛ŅŒŅ‚Đĩ ĐžŅ‚ĐˇŅ‹Đ˛" + +storage_full_message: + title: "ОбĐģĐ°Ņ‡ĐŊĐžĐĩ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đĩ ĐŋĐžŅ‡Ņ‚Đ¸ СаĐŋĐžĐģĐŊĐĩĐŊĐž ($1%)" + message: "Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžŅĐ˛ĐžĐąĐžĐ´Đ¸Ņ‚ŅŒ ĐŧĐĩŅŅ‚Đž, ŅƒĐ´Đ°Đģив ĐŊĐĩĐ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩĐŧŅ‹Đĩ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Đ¸." + +parse_error_message: + title: "ĐœŅ‹ ĐŊĐĩ ҁĐŧĐžĐŗĐģи ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Đ¸ иС Đ˛Đ°ŅˆĐĩĐŗĐž ОйĐģĐ°Ņ‡ĐŊĐžĐŗĐž Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ°." + message: "ĐŸĐžŅ…ĐžĐļĐĩ, ОйĐģĐ°Ņ‡ĐŊĐžĐĩ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đĩ ĐŋĐžĐ˛Ņ€ĐĩĐļĐ´ĐĩĐŊĐž. Đ§Ņ‚ĐžĐąŅ‹ ŅŅ‚Đž Đ¸ŅĐŋŅ€Đ°Đ˛Đ¸Ņ‚ŅŒ, Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ СаĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐĩĐŗĐž ĐģĐžĐēаĐģҌĐŊОК ĐēĐžĐŋиĐĩĐš." + action: "Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ĐģĐžĐēаĐģҌĐŊŅƒŅŽ ĐēĐžĐŋĐ¸ŅŽ" + +merge_conflict_message: + title: "В ĐģĐžĐēаĐģҌĐŊĐžĐŧ и ОйĐģĐ°Ņ‡ĐŊĐžĐŧ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ°Ņ… ĐĩŅŅ‚ŅŒ ĐēĐžĐŊŅ„ĐģиĐēŅ‚ŅƒŅŽŅ‰Đ¸Đĩ иСĐŧĐĩĐŊĐĩĐŊĐ¸Ņ." + message: "Đ§Ņ‚ĐžĐąŅ‹ ŅŅ‚Đž Đ¸ŅĐŋŅ€Đ°Đ˛Đ¸Ņ‚ŅŒ, Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ŅĐžŅ…Ņ€Đ°ĐŊĐ¸Ņ‚ŅŒ ĐģĐžĐēаĐģҌĐŊŅƒŅŽ ĐēĐžĐŋĐ¸ŅŽ в ОйĐģаĐēĐž, ĐģийО ĐŋŅ€Đ¸ĐŊŅŅ‚ŅŒ иСĐŧĐĩĐŊĐĩĐŊĐ¸Ņ иС ОйĐģаĐēа." + accept_local: "ЗаĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐģĐžĐēаĐģҌĐŊОК" + accept_cloud: "ĐŸŅ€Đ¸ĐŊŅŅ‚ŅŒ ОйĐģĐ°Ņ‡ĐŊŅ‹Đĩ иСĐŧĐĩĐŊĐĩĐŊĐ¸Ņ" diff --git a/locales/uk.yml b/locales/uk.yml new file mode 100644 index 0000000..939ecdd --- /dev/null +++ b/locales/uk.yml @@ -0,0 +1,245 @@ +manifest: + name: "Đ’Ņ–Đ´ĐēĐģадĐĩĐŊŅ– вĐēĐģадĐēи" + description: "Đ’Ņ–Đ´ĐēĐģĐ°Đ´Đ°ĐšŅ‚Đĩ Ņ‚Đ° ĐžŅ€ĐŗĐ°ĐŊŅ–ĐˇĐžĐ˛ŅƒĐšŅ‚Đĩ ŅĐ˛ĐžŅ— вĐēĐģадĐēи. ĐŸŅ€ĐžĐ´ĐžĐ˛ĐļŅ‚Đĩ С Ņ‚ĐžĐŗĐž ĐŧŅ–ŅŅ†Ņ, Đ´Đĩ ĐˇŅƒĐŋиĐŊиĐģĐ¸ŅŅ" + author: "Đ„Đ˛ĐŗĐĩĐŊ Đ›Đ¸Ņ" + +shortcuts: + toggle_sidebar: "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ ҁĐŋĐ¸ŅĐžĐē ĐēĐžĐģĐĩĐēŅ†Ņ–Đš" + set_aside: "Đ’Ņ–Đ´ĐēĐģĐ°ŅŅ‚Đ¸ вĐēĐģадĐēи" + save_tabs: "ЗбĐĩŅ€ĐĩĐŗŅ‚Đ¸ вĐēĐģадĐēи" + +common: + actions: + cancel: "ĐĄĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸" + save: "ЗбĐĩŅ€ĐĩĐŗŅ‚Đ¸" + close: "ЗаĐēŅ€Đ¸Ņ‚Đ¸" + delete: "ВидаĐģĐ¸Ņ‚Đ¸" + reset_filters: "ĐĄĐēиĐŊŅƒŅ‚Đ¸ ҄ҖĐģŅŒŅ‚Ņ€Đ¸" + cta: + feedback: "ЗаĐģĐ¸ŅˆĐ¸Ņ‚Đ¸ Đ˛Ņ–Đ´ĐŗŅƒĐē" + sponsor: "ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸" + tooltips: + more: "ĐŠĐĩ" + delete_prompt: "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–? ĐĻŅŽ Đ´Ņ–ŅŽ ĐŊĐĩ ĐŧĐžĐļĐŊа ҁĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸." + +features: + v3welcome: + title: "Đ›Đ°ŅĐēавО ĐŋŅ€ĐžŅĐ¸ĐŧĐž Đ´Đž Đ’Ņ–Đ´ĐēĐģадĐĩĐŊĐ¸Ņ… вĐēĐģадОĐē 3.0" + text1: "Ми Ņ€Đ°Đ´Ņ– ĐŋŅ€ĐĩĐ´ŅŅ‚Đ°Đ˛Đ¸Ņ‚Đ¸ ĐŊОвĐĩ вĐĩĐģиĐēĐĩ ĐžĐŊОвĐģĐĩĐŊĐŊŅ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ!" + text2: "ĐĻĐĩ ĐžĐŊОвĐģĐĩĐŊĐŊŅ вĐēĐģŅŽŅ‡Đ°Ņ” Đ°ĐąŅĐžĐģŅŽŅ‚ĐŊĐž ĐŊОвиК Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅ Ņ– ĐąĐĩСĐģҖ҇ ĐŊĐžĐ˛Đ¸Ņ… Ņ„ŅƒĐŊĐēŅ†Ņ–Đš, Ņ‚Đ°ĐēĐ¸Ņ… ŅĐē:" + list: + item1: "ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа ĐŗŅ€ŅƒĐŋŅƒĐ˛Đ°ĐŊĐŊŅ вĐēĐģадОĐē" + item2: "ПĐĩŅ€ŅĐžĐŊаĐģŅ–ĐˇĐ°Ņ†Ņ–Ņ ĐēĐžĐģĐĩĐēŅ†Ņ–Đš" + item3: "ПĐĩŅ€ĐĩŅ‚ŅĐŗŅƒĐ˛Đ°ĐŊĐŊŅ ĐēĐžĐģĐĩĐēŅ†Ņ–Đš Ņ‚Đ° ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛" + item4: "ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ ĐēĐžĐģĐĩĐēŅ†Ņ–Đš С ĐŊ҃ĐģŅ" + item5: "І ҉Đĩ ĐąĐ°ĐŗĐ°Ņ‚Đž Ņ–ĐŊŅˆĐžĐŗĐž!" + text3: "Đ’Ņ–Đ´Đ˛Ņ–Đ´Đ°ĐšŅ‚Đĩ ĐąĐģĐžĐŗ Ņ€ĐžĐˇŅ€ĐžĐąĐŊиĐēа (҂ҖĐģҌĐēи аĐŊĐŗĐģŅ–ĐšŅŅŒĐēĐžŅŽ), Ņ‰ĐžĐą Đ´Ņ–ĐˇĐŊĐ°Ņ‚Đ¸ŅŅ ĐąŅ–ĐģҌ҈Đĩ ĐŋŅ€Đž ҆Đĩ ĐžĐŊОвĐģĐĩĐŊĐŊŅ Ņ‚Đ° Đ˛ŅŅ– ĐšĐžĐŗĐž Ņ„ŅƒĐŊĐē҆Җҗ!" + actions: + visit_blog: "Đ§Đ¸Ņ‚Đ°Ņ‚Đ¸ ĐąĐģĐžĐŗ" + +notifications: + tabs_saved: + title: "ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž ĐŊĐžĐ˛Ņƒ ĐēĐžĐģĐĩĐēŅ†Ņ–ŅŽ" + message: "Đ’Đ°ŅˆŅ– вĐēĐģадĐēи СйĐĩŅ€ĐĩĐļĐĩĐŊĐž в ĐŊĐžĐ˛Ņƒ ĐēĐžĐģĐĩĐēŅ†Ņ–ŅŽ" + error_quota_exceeded: + title: "ПĐĩŅ€ĐĩĐ˛Đ¸Ņ‰ĐĩĐŊĐž ĐģŅ–ĐŧŅ–Ņ‚ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Đš СаĐŋĐ¸ŅŅƒ в Ņ…ĐŧĐ°Ņ€Ņ–" + message: "Ми СйĐĩŅ€ĐĩĐŗĐģи Đ˛Đ°ŅˆŅ– вĐēĐģадĐēи в ĐģĐžĐēаĐģҌĐŊĐžĐŧ҃ ŅŅ…ĐžĐ˛Đ¸Ņ‰Ņ–. ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐąŅƒĐ´Đĩ Đ˛Ņ€ŅƒŅ‡ĐŊ҃ ĐžĐŊĐžĐ˛Đ¸Ņ‚Đ¸ Ņ…ĐŧĐ°Ņ€ĐŊĐĩ ŅŅ…ĐžĐ˛Đ¸Ņ‰Đĩ" + error_storage_full: + title: "ĐĨĐŧĐ°Ņ€ĐŊĐĩ ŅŅ…ĐžĐ˛Đ¸Ņ‰Đĩ СаĐŋОвĐŊĐĩĐŊĐĩ" + message: "Ми СйĐĩŅ€ĐĩĐŗĐģи Đ˛Đ°ŅˆŅ– вĐēĐģадĐēи в ĐģĐžĐēаĐģҌĐŊĐžĐŧ҃ ŅŅ…ĐžĐ˛Đ¸Ņ‰Ņ–. Đ‘ŅƒĐ´ŅŒ ĐģĐ°ŅĐēа, ĐˇĐ˛Ņ–ĐģҌĐŊŅ–Ņ‚ŅŒ ĐŧҖҁ҆Đĩ в Ņ…ĐŧĐ°Ņ€ĐŊĐžĐŧ҃ ŅŅ…ĐžĐ˛Đ¸Ņ‰Ņ–" + bookmark_saved: + title: "ЕĐēҁĐŋĐžŅ€Ņ‚ĐžĐ˛Đ°ĐŊĐž в СаĐēĐģадĐēи" + message: "Đ’Đ°ŅˆĐ° ĐēĐžĐģĐĩĐēŅ†Ņ–Ņ ĐĩĐēҁĐŋĐžŅ€Ņ‚ĐžĐ˛Đ°ĐŊа в СаĐēĐģадĐēи" + partial_save: + title: "ДĐĩŅĐēŅ– вĐēĐģадĐēи ĐŊĐĩ ĐąŅƒĐģи СйĐĩŅ€ĐĩĐļĐĩĐŊŅ–" + message: "ДĐĩŅĐēŅ– С вĐēĐģадОĐē Ņ” ŅĐ¸ŅŅ‚ĐĩĐŧĐŊиĐŧи Ņ– ĐŊĐĩ ĐŧĐžĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ СйĐĩŅ€ĐĩĐļĐĩĐŊŅ–" + +actions: + save: + all: "ЗбĐĩŅ€ĐĩĐŗŅ‚Đ¸ Đ˛ŅŅ– вĐēĐģадĐēи" + selected: "ЗбĐĩŅ€ĐĩĐŗŅ‚Đ¸ Đ˛Đ¸ĐąŅ€Đ°ĐŊŅ– вĐēĐģадĐēи" + set_aside: + all: "Đ’Ņ–Đ´ĐēĐģĐ°ŅŅ‚Đ¸ Đ˛ŅŅ– вĐēĐģадĐēи" + selected: "Đ’Ņ–Đ´ĐēĐģĐ°ŅŅ‚Đ¸ Đ˛Đ¸ĐąŅ€Đ°ĐŊŅ– вĐēĐģадĐēи" + show_collections: "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ ҁĐŋĐ¸ŅĐžĐē ĐēĐžĐģĐĩĐēŅ†Ņ–Đš" + +options_page: + title: "НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ" + general: + title: "Đ—Đ°ĐŗĐ°ĐģҌĐŊŅ–" + options: + always_show_toolbars: "ЗавĐļди ĐŋĐžĐēĐ°ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋаĐŊĐĩĐģŅ– Đ´Ņ–Đš" + include_pinned: "ЗбĐĩŅ€Ņ–ĐŗĐ°Ņ‚Đ¸ СаĐēҀҖĐŋĐģĐĩĐŊŅ– вĐēĐģадĐēи ĐŋŅ€Đ¸ СйĐĩŅ€ĐĩĐļĐĩĐŊĐŊŅ– Đ˛ŅŅ–Ņ… вĐēĐģадОĐē" + show_delete_prompt: "ЗаĐŋĐ¸Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋŅ–Đ´Ņ‚Đ˛ĐĩŅ€Đ´ĐļĐĩĐŊĐŊŅ ĐŋŅ€Đ¸ видаĐģĐĩĐŊĐŊŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛" + show_badge: "ПоĐēĐ°ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ ĐģŅ–Ņ‡Đ¸ĐģҌĐŊиĐē" + show_notification: "ПоĐēĐ°ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ ҁĐŋĐžĐ˛Ņ–Ņ‰ĐĩĐŊĐŊŅ ĐŋŅ€Đ¸ СйĐĩŅ€ĐĩĐļĐĩĐŊĐŊŅ– ҇ĐĩŅ€ĐĩС ĐēĐžĐŊŅ‚ĐĩĐēҁ҂ĐŊĐĩ ĐŧĐĩĐŊŅŽ" + unload_tabs: "НĐĩ СаваĐŊŅ‚Đ°ĐļŅƒĐ˛Đ°Ņ‚Đ¸ вĐēĐģадĐēи ĐŋҖҁĐģŅ Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Ņ‚Ņ" + list_locations: + title: "Đ’Ņ–Đ´ĐēŅ€Đ¸Đ˛Đ°Ņ‚Đ¸ ҁĐŋĐ¸ŅĐžĐē ĐēĐžĐģĐĩĐēŅ†Ņ–Đš ҃:" + options: + sidebar: "Đ‘Ņ–Ņ‡ĐŊĐžŅ— ĐŋаĐŊĐĩĐģŅ–" + popup: "Đ’ŅĐŋĐģĐ¸Đ˛Đ°ŅŽŅ‡ĐžĐŧ҃ Đ˛Ņ–ĐēĐŊŅ–" + tab: "ОĐēŅ€ĐĩĐŧŅ–Đš вĐēĐģĐ°Đ´Ņ†Ņ–" + pinned: "ЗаĐēҀҖĐŋĐģĐĩĐŊŅ–Đš вĐēĐģĐ°Đ´Ņ†Ņ–" + icon_action: + title: "ĐŸŅ€Đ¸ ĐŊĐ°Ņ‚Đ¸ŅĐēаĐŊĐŊŅ– ĐŊа Ņ–ĐēĐžĐŊĐē҃ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ:" + options: + action: "ВиĐēĐžĐŊĐ°Ņ‚Đ¸ Đ´Ņ–ŅŽ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ" + context: "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ ĐēĐžĐŊŅ‚ĐĩĐēҁ҂ĐŊĐĩ ĐŧĐĩĐŊŅŽ" + open: "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ ҁĐŋĐ¸ŅĐžĐē ĐēĐžĐģĐĩĐēŅ†Ņ–Đš" + change_shortcuts: "ЗĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ĐŗĐ°Ņ€ŅŅ‡Ņ– ĐēĐģĐ°Đ˛Ņ–ŅˆŅ–" + actions: + title: "Đ”Ņ–Ņ—" + options: + save_actions: + title: "Đ”Ņ–Ņ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐŋŅ€Đ¸ СйĐĩŅ€ĐĩĐļĐĩĐŊĐŊŅ– вĐēĐģадОĐē" + options: + set_aside: "ЗбĐĩŅ€ĐĩĐŗŅ‚Đ¸ Ņ‚Đ° СаĐēŅ€Đ¸Ņ‚Đ¸ вĐēĐģадĐēи" + save: "ЗбĐĩŅ€ĐĩĐŗŅ‚Đ¸ вĐēĐģадĐēи, ĐŊĐĩ СаĐēŅ€Đ¸Đ˛Đ°ŅŽŅ‡Đ¸ Ņ—Ņ…" + restore_actions: + title: "Đ”Ņ–Ņ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐŋŅ€Đ¸ Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Ņ‚Ņ– ĐēĐžĐģĐĩĐēŅ†Ņ–Đš" + options: + open: "ĐŸŅ€ĐžŅŅ‚Đž Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ вĐēĐģадĐēи" + restore: "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ вĐēĐģадĐēи Ņ‚Đ° видаĐģĐ¸Ņ‚Đ¸ ĐēĐžĐģĐĩĐēŅ†Ņ–ŅŽ" + storage: + title: "ĐĄŅ…ĐžĐ˛Đ¸Ņ‰Đĩ" + capacity: + title: "ĐĨĐŧĐ°Ņ€ĐŊĐĩ ŅŅ…ĐžĐ˛Đ¸Ņ‰Đĩ" + description: "$1 С $2 ĐšŅ–Đ‘" + import: "ІĐŧĐŋĐžŅ€Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ даĐŊŅ–" + export: "ЕĐēҁĐŋĐžŅ€Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ даĐŊŅ–" + import_results: + success: "ДаĐŊŅ– ҃ҁĐŋŅ–ŅˆĐŊĐž Ņ–ĐŧĐŋĐžŅ€Ņ‚ĐžĐ˛Đ°ĐŊŅ–" + error: "ĐĄŅ…ĐžĐļĐĩ, Đ˛Đ¸ĐąŅ€Đ°ĐŊиК Ņ„Đ°ĐšĐģ ĐŋĐžŅˆĐēОдĐļĐĩĐŊиК. ĐŅ–Ņ‡ĐžĐŗĐž ĐŊĐĩ ĐąŅƒĐģĐž Ņ–ĐŧĐŋĐžŅ€Ņ‚ĐžĐ˛Đ°ĐŊĐž" + import_prompt: + title: "ІĐŧĐŋĐžŅ€Ņ‚ даĐŊĐ¸Ņ…" + warning_title: "ĐĻĐĩ ĐŊĐĩĐˇĐ˛ĐžŅ€ĐžŅ‚ĐŊа Đ´Ņ–Ņ!" + warning_text: "ВоĐŊа ĐŋĐĩŅ€ĐĩСаĐŋĐ¸ŅˆĐĩ Đ˛ŅŅ– Đ˛Đ°ŅˆŅ– даĐŊŅ–. ПĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž ви Đ˛Đ¸ĐąŅ€Đ°Đģи ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊиК Ņ„Đ°ĐšĐģ, Ņ–ĐŊаĐē҈Đĩ ҆Đĩ ĐŧĐžĐļĐĩ ĐŋŅ€Đ¸ĐˇĐ˛ĐĩŅŅ‚Đ¸ Đ´Đž ĐŋĐžŅˆĐēОдĐļĐĩĐŊĐŊŅ айО Đ˛Ņ‚Ņ€Đ°Ņ‚Đ¸ даĐŊĐ¸Ņ…. Đ ĐĩĐēĐžĐŧĐĩĐŊĐ´ŅƒŅ”Ņ‚ŅŒŅŅ ҁĐŋĐžŅ‡Đ°Ņ‚Đē҃ ĐĩĐēҁĐŋĐžŅ€Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ даĐŊŅ–." + proceed: "Đ’Đ¸ĐąŅ€Đ°Ņ‚Đ¸ Ņ„Đ°ĐšĐģ" + about: + title: "О Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ–" + developed_by: "Đ ĐžĐˇŅ€ĐžĐąĐŊиĐē: Đ„Đ˛ĐŗĐĩĐŊ Đ›Đ¸Ņ" + licensed_under: "" + mit_license: "Đ›Ņ–Ņ†ĐĩĐŊĐˇŅ–Ņ MIT" + translation_cta: + text: "ЗĐŊĐ°ĐšŅˆĐģи ĐŋĐžĐŧиĐģĐē҃ айО Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩĐēĐģад ĐŊа Đ˛Đ°ŅˆŅƒ ĐŧĐžĐ˛Ņƒ?" + button: "ĐŸĐžŅ‡ĐŊŅ–Ņ‚ŅŒ Ņ‚ŅƒŅ‚" + links: + website: "ĐœŅ–Đš вĐĩĐą-ŅĐ°ĐšŅ‚" + source: "Đ’Đ¸Ņ…Ņ–Đ´ĐŊиК ĐēОд" + changelog: "ĐĄĐŋĐ¸ŅĐžĐē СĐŧŅ–ĐŊ" + +collections: + empty: "ĐĻŅ ĐēĐžĐģĐĩĐēŅ†Ņ–Ņ ĐŋŅƒŅŅ‚Đ°" + tabs_count: "ВĐēĐģадОĐē: $1" + actions: + open: "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ Đ˛ŅŅ–" + restore: "Đ’Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ Đ˛ŅŅ–" + new_window: "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ ҃ ĐŊОвОĐŧ҃ Đ˛Ņ–ĐēĐŊŅ–" + incognito: + edge: "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ ҃ Đ˛Ņ–ĐēĐŊŅ– InPrivate" + firefox: "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ в ĐŋŅ€Đ¸Đ˛Đ°Ņ‚ĐŊĐžĐŧ҃ Đ˛Ņ–ĐēĐŊŅ–" + chrome: "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ в аĐŊĐžĐŊŅ–ĐŧĐŊĐžĐŧ҃ Đ˛Ņ–ĐēĐŊŅ–" + incognito_check: + title: "ĐŸĐžŅ‚Ņ€Ņ–ĐąĐĩĐŊ Đ´ĐžĐˇĐ˛Ņ–Đģ" + message: + edge: + p1: "Đ ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅŽ ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐž Đ´ĐžĐ´Đ°Ņ‚ĐēОвĐĩ дОСвОĐģĐĩĐŊĐŊŅ, Ņ‰ĐžĐą Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ вĐēĐģадĐēи в Ņ€ĐĩĐļиĐŧŅ– InPrivate" + p2: "ДĐģŅ Ņ†ŅŒĐžĐŗĐž ĐŊĐ°Ņ‚Đ¸ŅĐŊŅ–Ņ‚ŅŒ \"НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ\" Ņ– ĐŋĐžŅ‚Ņ–Đŧ Đ˛Ņ–Đ´ĐŧŅ–Ņ‚ŅŒŅ‚Đĩ ĐžĐŋŅ†Ņ–ŅŽ \"ДозвоĐģĐ¸Ņ‚Đ¸ Ņ€ĐĩĐļиĐŧ ĐŋŅ€Đ¸Đ˛Đ°Ņ‚ĐŊĐžŅŅ‚Ņ– InPrivate\"" + firefox: + p1: "Đ ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅŽ ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐž Đ´ĐžĐ´Đ°Ņ‚ĐēОвĐĩ дОСвОĐģĐĩĐŊĐŊŅ, Ņ‰ĐžĐą Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ вĐēĐģадĐēи в ĐŋŅ€Đ¸Đ˛Đ°Ņ‚ĐŊĐžĐŧ҃ Đ˛Ņ–ĐēĐŊŅ–" + p2: "ДĐģŅ Ņ†ŅŒĐžĐŗĐž ĐŊĐ°Ņ‚Đ¸ŅĐŊŅ–Ņ‚ŅŒ \"НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ\", ĐŋĐĩŅ€ĐĩĐšĐ´Ņ–Ņ‚ŅŒ ҃ \"ĐŸĐžĐ´Ņ€ĐžĐąĐ¸Ņ†Ņ–\" Ņ– дОСвОĐģŅŒŅ‚Đĩ \"ВиĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ в ĐŋŅ€Đ¸Đ˛Đ°Ņ‚ĐŊĐ¸Ņ… Đ˛Ņ–ĐēĐŊĐ°Ņ…\"" + chrome: + p1: "Đ ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅŽ ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐž Đ´ĐžĐ´Đ°Ņ‚ĐēОвĐĩ дОСвОĐģĐĩĐŊĐŊŅ, Ņ‰ĐžĐą Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ вĐēĐģадĐēи в аĐŊĐžĐŊŅ–ĐŧĐŊĐžĐŧ҃ Ņ€ĐĩĐļиĐŧŅ–" + p2: "ДĐģŅ Ņ†ŅŒĐžĐŗĐž ĐŊĐ°Ņ‚Đ¸ŅĐŊŅ–Ņ‚ŅŒ \"НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ\" Ņ– Đ˛Ņ–Đ´ĐŧŅ–Ņ‚ŅŒŅ‚Đĩ ĐžĐŋŅ†Ņ–ŅŽ \"ДозвоĐģĐ¸Ņ‚Đ¸ в аĐŊĐžĐŊŅ–ĐŧĐŊĐžĐŧ҃ Ņ€ĐĩĐļиĐŧŅ–\"" + action: "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи" + menu: + delete: "ВидаĐģĐ¸Ņ‚Đ¸ ĐēĐžĐģĐĩĐēŅ†Ņ–ŅŽ" + add_selected: "Đ”ĐžĐ´Đ°Ņ‚Đ¸ Đ˛Đ¸ĐąŅ€Đ°ĐŊŅ– вĐēĐģадĐēи" + add_group: "Đ”ĐžĐ´Đ°Ņ‚Đ¸ ĐŋĐžŅ€ĐžĐļĐŊŅŽ ĐŗŅ€ŅƒĐŋ҃" + add_pinned: "Đ”ĐžĐ´Đ°Ņ‚Đ¸ СаĐēҀҖĐŋĐģĐĩĐŊ҃ ĐŗŅ€ŅƒĐŋ҃" + export_bookmarks: "ЕĐēҁĐŋĐžŅ€Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ в СаĐēĐģадĐēи" + edit: "Đ ĐĩĐ´Đ°ĐŗŅƒĐ˛Đ°Ņ‚Đ¸ ĐēĐžĐģĐĩĐēŅ†Ņ–ŅŽ" + +groups: + title: "Đ“Ņ€ŅƒĐŋа" + pinned: "ЗаĐēҀҖĐŋĐģĐĩĐŊŅ–" + open: "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ Đ˛ŅŅ–" + empty: "ĐĻŅ ĐŗŅ€ŅƒĐŋа ĐŋŅƒŅŅ‚Đ°" + menu: + new_window: "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ ҃ ĐŊОвОĐŧ҃ Đ˛Ņ–ĐēĐŊŅ–" + add_selected: "Đ”ĐžĐ´Đ°Ņ‚Đ¸ Đ˛Đ¸ĐąŅ€Đ°ĐŊŅ– вĐēĐģадĐēи" + edit: "Đ ĐĩĐ´Đ°ĐŗŅƒĐ˛Đ°Ņ‚Đ¸ ĐŗŅ€ŅƒĐŋ҃" + ungroup: "Đ ĐžĐˇĐŗŅ€ŅƒĐŋŅƒĐ˛Đ°Ņ‚Đ¸" + delete: "ВидаĐģĐ¸Ņ‚Đ¸ ĐŗŅ€ŅƒĐŋ҃" + +tabs: + delete: "ВидаĐģĐ¸Ņ‚Đ¸ вĐēĐģадĐē҃" + +colors: + none: "БĐĩС ĐēĐžĐģŅŒĐžŅ€Ņƒ" + any: "Đ‘ŅƒĐ´ŅŒ-ŅĐēиК ĐēĐžĐģŅ–Ņ€" + grey: "ĐĄŅ–Ņ€Đ¸Đš" + blue: "ХиĐŊŅ–Đš" + red: "ЧĐĩŅ€Đ˛ĐžĐŊиК" + yellow: "Đ–ĐžĐ˛Ņ‚Đ¸Đš" + green: "ЗĐĩĐģĐĩĐŊиК" + pink: "Đ ĐžĐļĐĩвиК" + purple: "Đ¤Ņ–ĐžĐģĐĩŅ‚ĐžĐ˛Đ¸Đš" + cyan: "ГоĐģŅƒĐąĐ¸Đš" + orange: "ПоĐŧĐ°Ņ€Đ°ĐŊ҇ĐĩвиК" + +dialogs: + edit: + title: + edit_collection: "Đ ĐĩĐ´Đ°ĐŗŅƒĐ˛Đ°Ņ‚Đ¸ ĐēĐžĐģĐĩĐēŅ†Ņ–ŅŽ" + edit_group: "Đ ĐĩĐ´Đ°ĐŗŅƒĐ˛Đ°Ņ‚Đ¸ ĐŗŅ€ŅƒĐŋ҃" + new_group: "Нова ĐŗŅ€ŅƒĐŋа" + new_collection: "Нова ĐēĐžĐģĐĩĐēŅ†Ņ–Ņ" + collection_title: "Назва" + color: "КоĐģŅ–Ņ€" + +main: + header: + create_collection: "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐŊĐžĐ˛Ņƒ ĐēĐžĐģĐĩĐēŅ†Ņ–ŅŽ" + menu: + tiles_view: "ПĐģĐ¸Ņ‚Đēи" + changelog: "ĐŠĐž ĐŊĐžĐ˛ĐžĐŗĐž?" + list: + searchbar: + title: "ĐŸĐžŅˆŅƒĐē" + filter: "Đ¤Ņ–ĐģŅŒŅ‚Ņ€" + sort: + title: "ĐĄĐžŅ€Ņ‚ŅƒĐ˛Đ°ĐŊĐŊŅ" + options: + newest: "ĐĄĐŋĐžŅ‡Đ°Ņ‚Đē҃ ĐŊĐžĐ˛Ņ–" + oldest: "ĐĄĐŋĐžŅ‡Đ°Ņ‚Đē҃ ŅŅ‚Đ°Ņ€Ņ–" + ascending: "Đ’Ņ–Đ´ А Đ´Đž Đ¯" + descending: "Đ’Ņ–Đ´ Đ¯ Đ´Đž А" + custom: "ĐŸŅ€ĐžĐ¸ĐˇĐ˛ĐžĐģҌĐŊĐ°Ņ" + empty: + title: "ПоĐēи Ņ‰Đž Ņ‚ŅƒŅ‚ ĐŊŅ–Ņ‡ĐžĐŗĐž ĐŊĐĩĐŧĐ°Ņ”" + message: "Đ’Ņ–Đ´ĐēĐģĐ°Đ´Ņ–Ņ‚ŅŒ ĐŋĐžŅ‚ĐžŅ‡ĐŊŅ– вĐēĐģадĐēи айО ŅŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ ĐŊĐžĐ˛Ņƒ ĐēĐžĐģĐĩĐēŅ†Ņ–ŅŽ" + empty_search: + title: "ĐŅ–Ņ‡ĐžĐŗĐž ĐŊĐĩ СĐŊаКдĐĩĐŊĐž" + message: "ĐĄĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ СĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ĐŋĐžŅˆŅƒĐēОвиК СаĐŋĐ¸Ņ‚" + +cta_message: + title: "ĐŸĐžĐ´ĐžĐąĐ°Ņ”Ņ‚ŅŒŅŅ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ?" + message: "ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐ°ĐšŅ‚Đĩ Đ°Đ˛Ņ‚ĐžŅ€Đ° ĐŋĐžĐļĐĩŅ€Ņ‚Đ˛ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ айО" + feedback: "СаĐģĐ¸ŅˆŅ‚Đĩ Đ˛Ņ–Đ´ĐŗŅƒĐē" + +storage_full_message: + title: "ĐĨĐŧĐ°Ņ€ĐŊĐĩ ŅŅ…ĐžĐ˛Đ¸Ņ‰Đĩ ĐŧаКĐļĐĩ СаĐŋОвĐŊĐĩĐŊĐĩ ($1%)" + message: "Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇĐ˛Ņ–ĐģҌĐŊĐ¸Ņ‚Đ¸ ĐŧҖҁ҆Đĩ, видаĐģĐ¸Đ˛ŅˆĐ¸ ĐŊĐĩвиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°ĐŊŅ– ĐēĐžĐģĐĩĐē҆Җҗ." + +parse_error_message: + title: "Ми ĐŊĐĩ СĐŧĐžĐŗĐģи ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ ĐēĐžĐģĐĩĐē҆Җҗ С Đ˛Đ°ŅˆĐžĐŗĐž Ņ…ĐŧĐ°Ņ€ĐŊĐžĐŗĐž ŅŅ…ĐžĐ˛Đ¸Ņ‰Đ°." + message: "ĐĄŅ…ĐžĐļĐĩ, Ņ…ĐŧĐ°Ņ€ĐŊĐĩ ŅŅ…ĐžĐ˛Đ¸Ņ‰Đĩ ĐŋĐžŅˆĐēОдĐļĐĩĐŊĐĩ. ЊОй ҆Đĩ виĐŋŅ€Đ°Đ˛Đ¸Ņ‚Đ¸, ви ĐŧĐžĐļĐĩŅ‚Đĩ СаĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ĐšĐžĐŗĐž ĐģĐžĐēаĐģҌĐŊĐžŅŽ ĐēĐžĐŋŅ–Ņ”ŅŽ." + action: "ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ ĐģĐžĐēаĐģҌĐŊ҃ ĐēĐžĐŋŅ–ŅŽ" + +merge_conflict_message: + title: "В ĐģĐžĐēаĐģҌĐŊĐžĐŧ҃ Ņ– ОйĐģĐ°Ņ‡ĐŊĐžĐŧ҃ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ°Ņ… Ņ” ĐēĐžĐŊŅ„ĐģŅ–ĐēŅ‚ŅƒŅŽŅ‡Ņ– СĐŧŅ–ĐŊи." + message: "ЊОй ҆Đĩ виĐŋŅ€Đ°Đ˛Đ¸Ņ‚Đ¸, ви ĐŧĐžĐļĐĩŅ‚Đĩ СйĐĩŅ€ĐĩĐŗŅ‚Đ¸ ĐģĐžĐēаĐģҌĐŊ҃ ĐēĐžĐŋŅ–ŅŽ в Ņ…ĐŧĐ°Ņ€Ņ–, айО ĐŋŅ€Đ¸ĐšĐŊŅŅ‚Đ¸ СĐŧŅ–ĐŊи С Ņ…ĐŧĐ°Ņ€Đ¸." + accept_local: "ЗаĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐģĐžĐēаĐģҌĐŊĐžŅŽ" + accept_cloud: "ĐŸŅ€Đ¸ĐšĐŊŅŅ‚Đ¸ ОйĐģĐ°Ņ‡ĐŊŅ– СĐŧŅ–ĐŊи" diff --git a/models/CollectionModels.ts b/models/CollectionModels.ts new file mode 100644 index 0000000..31c4c30 --- /dev/null +++ b/models/CollectionModels.ts @@ -0,0 +1,41 @@ +export type TabItem = + { + type: "tab"; + url: string; + title?: string; + }; + +export type PinnedGroupItem = + { + type: "group"; + pinned: true; + items: TabItem[]; + }; + +export type DefaultGroupItem = + { + type: "group"; + pinned?: false; + title?: string; + color: chrome.tabGroups.ColorEnum; + items: TabItem[]; + }; + +export type GroupItem = PinnedGroupItem | DefaultGroupItem; + +export type CollectionItem = + { + type: "collection"; + timestamp: number; + title?: string; + color?: chrome.tabGroups.ColorEnum; + items: (TabItem | GroupItem)[]; + }; + +export type GraphicsStorage = Record; + +export type GraphicsItem = + { + preview?: string; + icon?: string; + }; diff --git a/package.json b/package.json new file mode 100644 index 0000000..e201f77 --- /dev/null +++ b/package.json @@ -0,0 +1,47 @@ +{ + "name": "tabs-aside", + "private": true, + "version": "3.0.0-rc1", + "type": "module", + "scripts": { + "dev": "wxt", + "build": "wxt build", + "zip": "wxt zip", + "lint": "npm run compile && eslint . -c eslint.config.js", + "prebuild": "npm run lint", + "prezip": "npm run build", + "compile": "tsc --noEmit", + "postinstall": "wxt prepare" + }, + "dependencies": { + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", + "@fluentui/react-components": "^9.63.0", + "@fluentui/react-icons": "^2.0.298", + "@webext-core/messaging": "^2.2.0", + "@wxt-dev/i18n": "^0.2.3", + "lzutf8": "^0.6.3", + "react": "^18.3.1", + "react-dom": "18.3.1" + }, + "devDependencies": { + "@eslint/css": "^0.7.0", + "@eslint/js": "^9.26.0", + "@eslint/json": "^0.12.0", + "@stylistic/eslint-plugin": "^4.2.0", + "@types/react": "^18.3.1", + "@types/react-dom": "^18.3.1", + "@wxt-dev/module-react": "^1.1.3", + "eslint": "^9.26.0", + "eslint-plugin-react": "^7.37.5", + "globals": "^16.0.0", + "scheduler": "0.23.0", + "typescript": "^5.8.3", + "typescript-eslint": "^8.31.1", + "vite": "^6.3.4", + "wxt": "~0.19.29" + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..a2fc7f2 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/icon/1024.png b/public/icon/1024.png new file mode 100644 index 0000000..fea6e6b Binary files /dev/null and b/public/icon/1024.png differ diff --git a/public/icon/128.png b/public/icon/128.png new file mode 100644 index 0000000..04302bd Binary files /dev/null and b/public/icon/128.png differ diff --git a/public/icon/16.png b/public/icon/16.png new file mode 100644 index 0000000..7caf8d5 Binary files /dev/null and b/public/icon/16.png differ diff --git a/public/icon/32.png b/public/icon/32.png new file mode 100644 index 0000000..36627da Binary files /dev/null and b/public/icon/32.png differ diff --git a/public/icon/48.png b/public/icon/48.png new file mode 100644 index 0000000..0a610a5 Binary files /dev/null and b/public/icon/48.png differ diff --git a/public/icon/96.png b/public/icon/96.png new file mode 100644 index 0000000..016877a Binary files /dev/null and b/public/icon/96.png differ diff --git a/public/notification_icons/bookmark_add.png b/public/notification_icons/bookmark_add.png new file mode 100644 index 0000000..395d060 Binary files /dev/null and b/public/notification_icons/bookmark_add.png differ diff --git a/public/notification_icons/cloud_checkmark.png b/public/notification_icons/cloud_checkmark.png new file mode 100644 index 0000000..9d7e446 Binary files /dev/null and b/public/notification_icons/cloud_checkmark.png differ diff --git a/public/notification_icons/cloud_error.png b/public/notification_icons/cloud_error.png new file mode 100644 index 0000000..f33c67b Binary files /dev/null and b/public/notification_icons/cloud_error.png differ diff --git a/public/notification_icons/save_warning.png b/public/notification_icons/save_warning.png new file mode 100644 index 0000000..405f543 Binary files /dev/null and b/public/notification_icons/save_warning.png differ diff --git a/public/promo/dark.webp b/public/promo/dark.webp new file mode 100644 index 0000000..0f1284e Binary files /dev/null and b/public/promo/dark.webp differ diff --git a/public/promo/light.webp b/public/promo/light.webp new file mode 100644 index 0000000..b47e365 Binary files /dev/null and b/public/promo/light.webp differ diff --git a/store_descriptions/en.txt b/store_descriptions/en.txt new file mode 100644 index 0000000..c2fb440 --- /dev/null +++ b/store_descriptions/en.txt @@ -0,0 +1,49 @@ + + +Stemming its roots from the original Microsoft Edge browser feature, this extension has grown much bigger than just a temporary storage for tabs. + +It allows you to save and manage your tabs in a convenient way, providing a range of features that make it easy to organize and access your saved tabs. + +## Features +- Save tabs: Save all your open tabs in a single click, and restore them later +- Organize tabs: Create collections and subgroups to organize your saved tabs +- Search tabs: Quickly find the tabs you need using the search feature +- Sync across devices: Access your saved tabs from any device with your account +- Go dark: Dark mode support for a more comfortable browsing experience +- Personalize: Change the appearance and behavior of the extension to suit your needs + +Check out our blog post regarding all the new features and improvements in Tabs aside 3.0 at: +https://at.xfox111.net/tabs-aside-3-0 + +## Hey, it's an open-source software! +If you know how to improve this extension you can check its GitHub Repository at: +https://github.com/xfox111/TabsAsideExtension + +Check out release changelog on: +https://github.com/xfox111/TabsAsideExtension/releases/latest + + + + + + +Stemming its roots from the original Microsoft Edge browser feature, this extension has grown much bigger than just a temporary storage for tabs. + +It allows you to save and manage your tabs in a convenient way, providing a range of features that make it easy to organize and access your saved tabs. + +Features +
    +
  • Save tabs: Save all your open tabs in a single click, and restore them later
  • +
  • Organize tabs: Create collections and subgroups to organize your saved tabs
  • +
  • Search tabs: Quickly find the tabs you need using the search feature
  • +
  • Sync across devices: Access your saved tabs from any device with your account
  • +
  • Go dark: Dark mode support for a more comfortable browsing experience
  • +
  • Personalize: Change the appearance and behavior of the extension to suit your needs
  • +
+ +Check out our blog post regarding all the new features and improvements in Tabs aside 3.0 + +Hey, it's an open-source software! +If you know how to improve this extension you can check its GitHub Repository + +Check out release changelog diff --git a/store_descriptions/ru.txt b/store_descriptions/ru.txt new file mode 100644 index 0000000..716c64f --- /dev/null +++ b/store_descriptions/ru.txt @@ -0,0 +1,48 @@ + + +Đ’Đ´ĐžŅ…ĐŊОвĐģĐĩĐŊĐŊĐžĐĩ Ņ„ŅƒĐŊĐēŅ†Đ¸ĐĩĐš ĐŋŅ€ĐĩĐ˛Ņ‹Ņ… вĐĩŅ€ŅĐ¸Đš ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Đ° Microsoft Edge, ŅŅ‚Đž Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊиĐĩ ŅŅ‚Đ°ĐģĐž ĐŗĐžŅ€Đ°ĐˇĐ´Đž йОĐģҌ҈Đĩ, ҇ĐĩĐŧ ĐŋŅ€ĐžŅŅ‚Đž Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊĐžĐĩ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đĩ Đ´ĐģŅ вĐēĐģадОĐē. + +ОĐŊĐž ĐŋОСвОĐģŅĐĩŅ‚ ŅĐžŅ…Ņ€Đ°ĐŊŅŅ‚ŅŒ и ҃ĐŋŅ€Đ°Đ˛ĐģŅŅ‚ŅŒ Đ˛Đ°ŅˆĐ¸Đŧи вĐēĐģадĐēаĐŧи ŅƒĐ´ĐžĐąĐŊŅ‹Đŧ ĐžĐąŅ€Đ°ĐˇĐžĐŧ, ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ĐģŅŅ ĐŧĐŊĐžĐļĐĩŅŅ‚Đ˛Đž Ņ„ŅƒĐŊĐēŅ†Đ¸Đš, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ҃ĐŋŅ€ĐžŅ‰Đ°ŅŽŅ‚ ĐžŅ€ĐŗĐ°ĐŊĐ¸ĐˇĐ°Ņ†Đ¸ŅŽ и Đ´ĐžŅŅ‚ŅƒĐŋ Đē ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊĐŊŅ‹Đŧ вĐēĐģадĐēаĐŧ. + +## ВозĐŧĐžĐļĐŊĐžŅŅ‚Đ¸ +- ĐĄĐžŅ…Ņ€Đ°ĐŊĐĩĐŊиĐĩ вĐēĐģадОĐē: ĐĄĐžŅ…Ņ€Đ°ĐŊĐ¸Ņ‚Đĩ Đ˛ŅĐĩ ĐžŅ‚ĐēҀҋ҂ҋĐĩ вĐēĐģадĐēи ОдĐŊиĐŧ ĐēĐģиĐēĐžĐŧ и Đ˛ĐžŅŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đĩ Đ¸Ņ… ĐŋОСĐļĐĩ +- ĐžŅ€ĐŗĐ°ĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ вĐēĐģадОĐē: ĐĄĐžĐˇĐ´Đ°Đ˛Đ°ĐšŅ‚Đĩ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Đ¸ и ĐŋĐžĐ´ĐŗŅ€ŅƒĐŋĐŋŅ‹ Đ´ĐģŅ ĐžŅ€ĐŗĐ°ĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸ ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊĐŊҋ҅ вĐēĐģадОĐē +- ĐŸĐžĐ¸ŅĐē вĐēĐģадОĐē: Đ‘Ņ‹ŅŅ‚Ņ€Đž ĐŊĐ°Ņ…ĐžĐ´Đ¸Ņ‚Đĩ ĐŊ҃ĐļĐŊŅ‹Đĩ вĐēĐģадĐēи ҁ ĐŋĐžĐŧĐžŅ‰ŅŒŅŽ Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸ ĐŋĐžĐ¸ŅĐēа +- ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ ĐŧĐĩĐļĐ´Ņƒ ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°Đŧи: Đ”ĐžŅŅ‚ŅƒĐŋ Đē ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊĐŊŅ‹Đŧ вĐēĐģадĐēаĐŧ ҁ ĐģŅŽĐąĐžĐŗĐž ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ° ҇ĐĩŅ€ĐĩС Đ˛Đ°Ņˆ аĐēĐēĐ°ŅƒĐŊŅ‚ +- ĐĸĐĩĐŧĐŊŅ‹Đš Ņ€ĐĩĐļиĐŧ: ПоддĐĩŅ€ĐļĐēа Ņ‚ĐĩĐŧĐŊĐžĐŗĐž Ņ€ĐĩĐļиĐŧа Đ´ĐģŅ йОĐģĐĩĐĩ ĐēĐžĐŧŅ„ĐžŅ€Ņ‚ĐŊĐžĐŗĐž Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊĐ¸Ņ +- ПĐĩŅ€ŅĐžĐŊаĐģĐ¸ĐˇĐ°Ņ†Đ¸Ņ: ИСĐŧĐĩĐŊŅĐšŅ‚Đĩ вĐŊĐĩ҈ĐŊиК вид и ĐŋОвĐĩĐ´ĐĩĐŊиĐĩ Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐ¸Ņ ĐŋОд ŅĐ˛ĐžĐ¸ ĐŊ҃ĐļĐ´Ņ‹ + +ĐŸĐžŅĐĩŅ‚Đ¸Ņ‚Đĩ ĐŊĐ°Ņˆ ĐąĐģĐžĐŗ, Ņ‡Ņ‚ĐžĐąŅ‹ ŅƒĐˇĐŊĐ°Ņ‚ŅŒ йОĐģҌ҈Đĩ Đž Đ˛ŅĐĩŅ… ĐŊĐžĐ˛Ņ‹Ņ… Ņ„ŅƒĐŊĐēŅ†Đ¸ŅŅ… и ҃ĐģŅƒŅ‡ŅˆĐĩĐŊĐ¸ŅŅ… в ĐžŅ‚ĐģĐžĐļĐĩĐŊĐŊҋ҅ вĐēĐģадĐēĐ°Ņ… 3.0 ĐŋĐž ҁҁҋĐģĐēĐĩ: +https://at.xfox111.net/tabs-aside-3-0 + +## ĐšŅŅ‚Đ°Ņ‚Đ¸ ŅŅ‚Đž ĐžĐŋĐĩĐŊŅĐžŅ€Ņ Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊиĐĩ! +Đ•ŅĐģи Đ˛Ņ‹ СĐŊаĐĩŅ‚Đĩ, ĐēаĐē ĐŧĐžĐļĐŊĐž ĐĩĐŗĐž ҃ĐģŅƒŅ‡ŅˆĐ¸Ņ‚ŅŒ, ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩĐšŅ‚Đ¸ ĐŊа ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ†Ņƒ GitHub Ņ€ĐĩĐŋĐžĐˇĐ¸Ņ‚ĐžŅ€Đ¸Ņ ĐŋŅ€ĐžĐĩĐēŅ‚Đ°: +https://github.com/xfox111/TabsAsideExtension + +ĐĄĐŋĐ¸ŅĐžĐē иСĐŧĐĩĐŊĐĩĐŊиК ĐŋĐžŅĐģĐĩĐ´ĐŊĐĩĐš вĐĩŅ€ŅĐ¸Đ¸: +https://github.com/xfox111/TabsAsideExtension/releases/latest + + + + + +Đ’Đ´ĐžŅ…ĐŊОвĐģĐĩĐŊĐŊĐžĐĩ Ņ„ŅƒĐŊĐēŅ†Đ¸ĐĩĐš ĐŋŅ€ĐĩĐ˛Ņ‹Ņ… вĐĩŅ€ŅĐ¸Đš ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Đ° Microsoft Edge, ŅŅ‚Đž Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊиĐĩ ŅŅ‚Đ°ĐģĐž ĐŗĐžŅ€Đ°ĐˇĐ´Đž йОĐģҌ҈Đĩ, ҇ĐĩĐŧ ĐŋŅ€ĐžŅŅ‚Đž Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊĐžĐĩ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đĩ Đ´ĐģŅ вĐēĐģадОĐē. + +ОĐŊĐž ĐŋОСвОĐģŅĐĩŅ‚ ŅĐžŅ…Ņ€Đ°ĐŊŅŅ‚ŅŒ и ҃ĐŋŅ€Đ°Đ˛ĐģŅŅ‚ŅŒ Đ˛Đ°ŅˆĐ¸Đŧи вĐēĐģадĐēаĐŧи ŅƒĐ´ĐžĐąĐŊŅ‹Đŧ ĐžĐąŅ€Đ°ĐˇĐžĐŧ, ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ĐģŅŅ ĐŧĐŊĐžĐļĐĩŅŅ‚Đ˛Đž Ņ„ŅƒĐŊĐēŅ†Đ¸Đš, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ҃ĐŋŅ€ĐžŅ‰Đ°ŅŽŅ‚ ĐžŅ€ĐŗĐ°ĐŊĐ¸ĐˇĐ°Ņ†Đ¸ŅŽ и Đ´ĐžŅŅ‚ŅƒĐŋ Đē ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊĐŊŅ‹Đŧ вĐēĐģадĐēаĐŧ. + +ВозĐŧĐžĐļĐŊĐžŅŅ‚Đ¸ +
    +
  • ĐĄĐžŅ…Ņ€Đ°ĐŊĐĩĐŊиĐĩ вĐēĐģадОĐē: ĐĄĐžŅ…Ņ€Đ°ĐŊĐ¸Ņ‚Đĩ Đ˛ŅĐĩ ĐžŅ‚ĐēҀҋ҂ҋĐĩ вĐēĐģадĐēи ОдĐŊиĐŧ ĐēĐģиĐēĐžĐŧ и Đ˛ĐžŅŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đĩ Đ¸Ņ… ĐŋОСĐļĐĩ
  • +
  • ĐžŅ€ĐŗĐ°ĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ вĐēĐģадОĐē: ĐĄĐžĐˇĐ´Đ°Đ˛Đ°ĐšŅ‚Đĩ ĐēĐžĐģĐģĐĩĐēŅ†Đ¸Đ¸ и ĐŋĐžĐ´ĐŗŅ€ŅƒĐŋĐŋŅ‹ Đ´ĐģŅ ĐžŅ€ĐŗĐ°ĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸ ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊĐŊҋ҅ вĐēĐģадОĐē
  • +
  • ĐŸĐžĐ¸ŅĐē вĐēĐģадОĐē: Đ‘Ņ‹ŅŅ‚Ņ€Đž ĐŊĐ°Ņ…ĐžĐ´Đ¸Ņ‚Đĩ ĐŊ҃ĐļĐŊŅ‹Đĩ вĐēĐģадĐēи ҁ ĐŋĐžĐŧĐžŅ‰ŅŒŅŽ Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸ ĐŋĐžĐ¸ŅĐēа
  • +
  • ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ ĐŧĐĩĐļĐ´Ņƒ ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°Đŧи: Đ”ĐžŅŅ‚ŅƒĐŋ Đē ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊĐŊŅ‹Đŧ вĐēĐģадĐēаĐŧ ҁ ĐģŅŽĐąĐžĐŗĐž ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ° ҇ĐĩŅ€ĐĩС Đ˛Đ°Ņˆ аĐēĐēĐ°ŅƒĐŊŅ‚
  • +
  • ĐĸĐĩĐŧĐŊŅ‹Đš Ņ€ĐĩĐļиĐŧ: ПоддĐĩŅ€ĐļĐēа Ņ‚ĐĩĐŧĐŊĐžĐŗĐž Ņ€ĐĩĐļиĐŧа Đ´ĐģŅ йОĐģĐĩĐĩ ĐēĐžĐŧŅ„ĐžŅ€Ņ‚ĐŊĐžĐŗĐž Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊĐ¸Ņ
  • +
  • ПĐĩŅ€ŅĐžĐŊаĐģĐ¸ĐˇĐ°Ņ†Đ¸Ņ: ИСĐŧĐĩĐŊŅĐšŅ‚Đĩ вĐŊĐĩ҈ĐŊиК вид и ĐŋОвĐĩĐ´ĐĩĐŊиĐĩ Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐ¸Ņ ĐŋОд ŅĐ˛ĐžĐ¸ ĐŊ҃ĐļĐ´Ņ‹
  • +
+ +ĐŸĐžŅĐĩŅ‚Đ¸Ņ‚Đĩ ĐŊĐ°Ņˆ ĐąĐģĐžĐŗ, Ņ‡Ņ‚ĐžĐąŅ‹ ŅƒĐˇĐŊĐ°Ņ‚ŅŒ йОĐģҌ҈Đĩ Đž Đ˛ŅĐĩŅ… ĐŊĐžĐ˛Ņ‹Ņ… Ņ„ŅƒĐŊĐēŅ†Đ¸ŅŅ… и ҃ĐģŅƒŅ‡ŅˆĐĩĐŊĐ¸ŅŅ… в ĐžŅ‚ĐģĐžĐļĐĩĐŊĐŊҋ҅ вĐēĐģадĐēĐ°Ņ… 3.0 ĐŋĐž ҁҁҋĐģĐēĐĩ + +ĐšŅŅ‚Đ°Ņ‚Đ¸ ŅŅ‚Đž ĐžĐŋĐĩĐŊŅĐžŅ€Ņ Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊиĐĩ! +Đ•ŅĐģи Đ˛Ņ‹ СĐŊаĐĩŅ‚Đĩ, ĐēаĐē ĐŧĐžĐļĐŊĐž ĐĩĐŗĐž ҃ĐģŅƒŅ‡ŅˆĐ¸Ņ‚ŅŒ, ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩĐšŅ‚Đ¸ ĐŊа ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ†Ņƒ GitHub Ņ€ĐĩĐŋĐžĐˇĐ¸Ņ‚ĐžŅ€Đ¸Ņ ĐŋŅ€ĐžĐĩĐēŅ‚Đ° + +ĐĄĐŋĐ¸ŅĐžĐē иСĐŧĐĩĐŊĐĩĐŊиК ĐŋĐžŅĐģĐĩĐ´ĐŊĐĩĐš вĐĩŅ€ŅĐ¸Đ¸ diff --git a/store_descriptions/uk.txt b/store_descriptions/uk.txt new file mode 100644 index 0000000..598586d --- /dev/null +++ b/store_descriptions/uk.txt @@ -0,0 +1,48 @@ + + +ĐĐ°Đ´Đ¸Ņ…ĐŊŅƒŅ‚Đĩ Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ”ŅŽ ĐŋĐĩŅ€ŅˆĐ¸Ņ… вĐĩŅ€ŅŅ–Đš Microsoft Edge, ҆Đĩ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ ŅŅ‚Đ°ĐģĐž ĐŊĐ°ĐąĐ°ĐŗĐ°Ņ‚Đž ĐąŅ–ĐģҌ҈Đĩ, ĐŊŅ–Đļ ĐŋŅ€ĐžŅŅ‚Đž Ņ‚Đ¸ĐŧŅ‡Đ°ŅĐžĐ˛Đĩ ŅŅ…ĐžĐ˛Đ¸Ņ‰Đĩ Đ´ĐģŅ вĐēĐģадОĐē. + +ВоĐŊĐž дОСвОĐģŅŅ” СйĐĩŅ€Ņ–ĐŗĐ°Ņ‚Đ¸ Ņ‚Đ° ĐēĐĩŅ€ŅƒĐ˛Đ°Ņ‚Đ¸ Đ˛Đ°ŅˆĐ¸Đŧи вĐēĐģадĐēаĐŧи ĐˇŅ€ŅƒŅ‡ĐŊĐž, ĐŊĐ°Đ´Đ°ŅŽŅ‡Đ¸ ĐąĐĩСĐģҖ҇ Ņ„ŅƒĐŊĐēŅ†Ņ–Đš, ŅĐēŅ– ҁĐŋŅ€ĐžŅ‰ŅƒŅŽŅ‚ŅŒ ĐžŅ€ĐŗĐ°ĐŊŅ–ĐˇĐ°Ņ†Ņ–ŅŽ Ņ‚Đ° Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž СйĐĩŅ€ĐĩĐļĐĩĐŊĐ¸Ņ… вĐēĐģадОĐē. + +## МоĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ– +- ЗбĐĩŅ€ĐĩĐļĐĩĐŊĐŊŅ вĐēĐģадОĐē: ЗбĐĩŅ€ĐĩĐļŅ–Ņ‚ŅŒ ŅƒŅŅ– Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Ņ– вĐēĐģадĐēи ОдĐŊиĐŧ ĐēĐģŅ–ĐēĐžĐŧ Ņ– Đ˛Ņ–Đ´ĐŊĐžĐ˛Ņ–Ņ‚ŅŒ Ņ—Ņ… ĐŋŅ–ĐˇĐŊŅ–ŅˆĐĩ +- ĐžŅ€ĐŗĐ°ĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ вĐēĐģадОĐē: ĐĄŅ‚Đ˛ĐžŅ€ŅŽĐšŅ‚Đĩ ĐēĐžĐģĐĩĐē҆Җҗ Ņ‚Đ° ĐŋŅ–Đ´ĐŗŅ€ŅƒĐŋи Đ´ĐģŅ ĐžŅ€ĐŗĐ°ĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ— СйĐĩŅ€ĐĩĐļĐĩĐŊĐ¸Ņ… вĐēĐģадОĐē +- ĐŸĐžŅˆŅƒĐē вĐēĐģадОĐē: ШвидĐēĐž СĐŊĐ°Ņ…ĐžĐ´ŅŒŅ‚Đĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊŅ– вĐēĐģадĐēи Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ Ņ„ŅƒĐŊĐē҆Җҗ ĐŋĐžŅˆŅƒĐē҃ +- ХиĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ ĐŧŅ–Đļ ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅĐŧи: Đ”ĐžŅŅ‚ŅƒĐŋ Đ´Đž СйĐĩŅ€ĐĩĐļĐĩĐŊĐ¸Ņ… вĐēĐģадОĐē С ĐąŅƒĐ´ŅŒ-ŅĐēĐžĐŗĐž ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ ҇ĐĩŅ€ĐĩС Đ˛Đ°Ņˆ ОйĐģŅ–ĐēОвиК СаĐŋĐ¸Ņ +- ĐĸĐĩĐŧĐŊиК Ņ€ĐĩĐļиĐŧ: ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа Ņ‚ĐĩĐŧĐŊĐžĐŗĐž Ņ€ĐĩĐļиĐŧ҃ Đ´ĐģŅ ĐąŅ–ĐģҌ҈ ĐēĐžĐŧŅ„ĐžŅ€Ņ‚ĐŊĐžĐŗĐž виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ +- ПĐĩŅ€ŅĐžĐŊаĐģŅ–ĐˇĐ°Ņ†Ņ–Ņ: ЗĐŧŅ–ĐŊŅŽĐšŅ‚Đĩ СОвĐŊŅ–ŅˆĐŊŅ–Đš Đ˛Đ¸ĐŗĐģŅĐ´ Ņ– ĐŋОвĐĩĐ´Ņ–ĐŊĐē҃ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ ĐŋŅ–Đ´ ŅĐ˛ĐžŅ— ĐŋĐžŅ‚Ņ€Đĩйи + +Đ’Ņ–Đ´Đ˛Ņ–Đ´Đ°ĐšŅ‚Đĩ ĐŊĐ°Ņˆ ĐąĐģĐžĐŗ, Ņ‰ĐžĐą Đ´Ņ–ĐˇĐŊĐ°Ņ‚Đ¸ŅŅ ĐąŅ–ĐģҌ҈Đĩ ĐŋŅ€Đž Đ˛ŅŅ– ĐŊĐžĐ˛Ņ– Ņ„ŅƒĐŊĐē҆Җҗ Ņ‚Đ° ĐŋĐžĐēŅ€Đ°Ņ‰ĐĩĐŊĐŊŅ ҃ Đ’Ņ–Đ´ĐēĐģадĐĩĐŊĐ¸Ņ… вĐēĐģадĐēĐ°Ņ… 3.0 Са ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅĐŧ: +https://at.xfox111.net/tabs-aside-3-0 + +## До Ņ€Đĩ҇Җ, ҆Đĩ ĐžĐŋĐĩĐŊŅĐžŅ€Ņ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ! +Đ¯ĐēŅ‰Đž ви СĐŊĐ°Ņ”Ņ‚Đĩ, ŅĐē ĐŋĐžĐēŅ€Đ°Ņ‰Đ¸Ņ‚Đ¸ ҆Đĩ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ, ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛Ņ–Đ´Đ˛Ņ–Đ´Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž Ņ€ĐĩĐŋĐžĐˇĐ¸Ņ‚ĐžŅ€Ņ–Đš ĐŊа GitHub: +https://github.com/xfox111/TabsAsideExtension + +ĐĄĐŋĐ¸ŅĐžĐē СĐŧŅ–ĐŊ ĐžŅŅ‚Đ°ĐŊĐŊŅŒĐžŅ— вĐĩҀҁҖҗ: +https://github.com/xfox111/TabsAsideExtension/releases/latest + + + + + +ĐĐ°Đ´Đ¸Ņ…ĐŊŅƒŅ‚Đĩ Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ”ŅŽ ĐŋĐĩŅ€ŅˆĐ¸Ņ… вĐĩŅ€ŅŅ–Đš Microsoft Edge, ҆Đĩ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ ŅŅ‚Đ°ĐģĐž ĐŊĐ°ĐąĐ°ĐŗĐ°Ņ‚Đž ĐąŅ–ĐģҌ҈Đĩ, ĐŊŅ–Đļ ĐŋŅ€ĐžŅŅ‚Đž Ņ‚Đ¸ĐŧŅ‡Đ°ŅĐžĐ˛Đĩ ŅŅ…ĐžĐ˛Đ¸Ņ‰Đĩ Đ´ĐģŅ вĐēĐģадОĐē. + +ВоĐŊĐž дОСвОĐģŅŅ” СйĐĩŅ€Ņ–ĐŗĐ°Ņ‚Đ¸ Ņ‚Đ° ĐēĐĩŅ€ŅƒĐ˛Đ°Ņ‚Đ¸ Đ˛Đ°ŅˆĐ¸Đŧи вĐēĐģадĐēаĐŧи ĐˇŅ€ŅƒŅ‡ĐŊĐž, ĐŊĐ°Đ´Đ°ŅŽŅ‡Đ¸ ĐąĐĩСĐģҖ҇ Ņ„ŅƒĐŊĐēŅ†Ņ–Đš, ŅĐēŅ– ҁĐŋŅ€ĐžŅ‰ŅƒŅŽŅ‚ŅŒ ĐžŅ€ĐŗĐ°ĐŊŅ–ĐˇĐ°Ņ†Ņ–ŅŽ Ņ‚Đ° Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž СйĐĩŅ€ĐĩĐļĐĩĐŊĐ¸Ņ… вĐēĐģадОĐē. + +МоĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ– +
    +
  • ЗбĐĩŅ€ĐĩĐļĐĩĐŊĐŊŅ вĐēĐģадОĐē: ЗбĐĩŅ€ĐĩĐļŅ–Ņ‚ŅŒ ŅƒŅŅ– Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Ņ– вĐēĐģадĐēи ОдĐŊиĐŧ ĐēĐģŅ–ĐēĐžĐŧ Ņ– Đ˛Ņ–Đ´ĐŊĐžĐ˛Ņ–Ņ‚ŅŒ Ņ—Ņ… ĐŋŅ–ĐˇĐŊŅ–ŅˆĐĩ
  • +
  • ĐžŅ€ĐŗĐ°ĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ вĐēĐģадОĐē: ĐĄŅ‚Đ˛ĐžŅ€ŅŽĐšŅ‚Đĩ ĐēĐžĐģĐĩĐē҆Җҗ Ņ‚Đ° ĐŋŅ–Đ´ĐŗŅ€ŅƒĐŋи Đ´ĐģŅ ĐžŅ€ĐŗĐ°ĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ— СйĐĩŅ€ĐĩĐļĐĩĐŊĐ¸Ņ… вĐēĐģадОĐē
  • +
  • ĐŸĐžŅˆŅƒĐē вĐēĐģадОĐē: ШвидĐēĐž СĐŊĐ°Ņ…ĐžĐ´ŅŒŅ‚Đĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊŅ– вĐēĐģадĐēи Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ Ņ„ŅƒĐŊĐē҆Җҗ ĐŋĐžŅˆŅƒĐē҃
  • +
  • ХиĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ ĐŧŅ–Đļ ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅĐŧи: Đ”ĐžŅŅ‚ŅƒĐŋ Đ´Đž СйĐĩŅ€ĐĩĐļĐĩĐŊĐ¸Ņ… вĐēĐģадОĐē С ĐąŅƒĐ´ŅŒ-ŅĐēĐžĐŗĐž ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ ҇ĐĩŅ€ĐĩС Đ˛Đ°Ņˆ ОйĐģŅ–ĐēОвиК СаĐŋĐ¸Ņ
  • +
  • ĐĸĐĩĐŧĐŊиК Ņ€ĐĩĐļиĐŧ: ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа Ņ‚ĐĩĐŧĐŊĐžĐŗĐž Ņ€ĐĩĐļиĐŧ҃ Đ´ĐģŅ ĐąŅ–ĐģҌ҈ ĐēĐžĐŧŅ„ĐžŅ€Ņ‚ĐŊĐžĐŗĐž виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ
  • +
  • ПĐĩŅ€ŅĐžĐŊаĐģŅ–ĐˇĐ°Ņ†Ņ–Ņ: ЗĐŧŅ–ĐŊŅŽĐšŅ‚Đĩ СОвĐŊŅ–ŅˆĐŊŅ–Đš Đ˛Đ¸ĐŗĐģŅĐ´ Ņ– ĐŋОвĐĩĐ´Ņ–ĐŊĐē҃ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ ĐŋŅ–Đ´ ŅĐ˛ĐžŅ— ĐŋĐžŅ‚Ņ€Đĩйи
  • +
+ +Đ’Ņ–Đ´Đ˛Ņ–Đ´Đ°ĐšŅ‚Đĩ ĐŊĐ°Ņˆ ĐąĐģĐžĐŗ, Ņ‰ĐžĐą Đ´Ņ–ĐˇĐŊĐ°Ņ‚Đ¸ŅŅ ĐąŅ–ĐģҌ҈Đĩ ĐŋŅ€Đž Đ˛ŅŅ– ĐŊĐžĐ˛Ņ– Ņ„ŅƒĐŊĐē҆Җҗ Ņ‚Đ° ĐŋĐžĐēŅ€Đ°Ņ‰ĐĩĐŊĐŊŅ ҃ Đ’Ņ–Đ´ĐēĐģадĐĩĐŊĐ¸Ņ… вĐēĐģадĐēĐ°Ņ… 3.0 + +До Ņ€Đĩ҇Җ, ҆Đĩ ĐžĐŋĐĩĐŊŅĐžŅ€Ņ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ! +Đ¯ĐēŅ‰Đž ви СĐŊĐ°Ņ”Ņ‚Đĩ, ŅĐē ĐŋĐžĐēŅ€Đ°Ņ‰Đ¸Ņ‚Đ¸ ҆Đĩ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ, ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛Ņ–Đ´Đ˛Ņ–Đ´Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž Ņ€ĐĩĐŋĐžĐˇĐ¸Ņ‚ĐžŅ€Ņ–Đš ĐŊа GitHub + +ĐĄĐŋĐ¸ŅĐžĐē СĐŧŅ–ĐŊ ĐžŅŅ‚Đ°ĐŊĐŊŅŒĐžŅ— вĐĩҀҁҖҗ diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..f39bbb5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "./.wxt/tsconfig.json", + "compilerOptions": { + "allowImportingTsExtensions": true, + "jsx": "react-jsx", + "strict": true, + "strictNullChecks": true + } +} diff --git a/utils/browserLocaleKey.ts b/utils/browserLocaleKey.ts new file mode 100644 index 0000000..0b2979a --- /dev/null +++ b/utils/browserLocaleKey.ts @@ -0,0 +1,8 @@ +const browserLocaleKey: "firefox" | "edge" | "chrome" = + import.meta.env.FIREFOX ? + "firefox" : + import.meta.env.EDGE ? + "edge" : + "chrome"; + +export default browserLocaleKey; diff --git a/utils/extLink.ts b/utils/extLink.ts new file mode 100644 index 0000000..e3ccc98 --- /dev/null +++ b/utils/extLink.ts @@ -0,0 +1,7 @@ +const extLink = (href: string) => ({ + href, + target: "_blank", + rel: "noopener" +}); + +export default extLink; diff --git a/utils/getLogger.ts b/utils/getLogger.ts new file mode 100644 index 0000000..0aacb49 --- /dev/null +++ b/utils/getLogger.ts @@ -0,0 +1,13 @@ +/** + * Creates a logger function for a specific component. + * The logger prepends a standardized prefix to all log messages, + * indicating the component name for easier debugging. + * + * @param component - The name of the component to include in the log prefix. + * @returns A logging function that accepts any number of arguments and logs them + * to the console with the component-specific prefix. + */ +export default function getLogger(component: string): (...data: any[]) => void +{ + return (...data: any[]): void => console.log(`[TabsAside.${component}]`, ...data); +} diff --git a/utils/messaging.ts b/utils/messaging.ts new file mode 100644 index 0000000..d7dfbdf --- /dev/null +++ b/utils/messaging.ts @@ -0,0 +1,26 @@ +import { GraphicsStorage } from "@/models/CollectionModels"; +import { defineExtensionMessaging, ExtensionMessenger } from "@webext-core/messaging"; + +type ProtocolMap = + { + addThumbnail(data: { url: string; thumbnail: string; }): void; + getGraphicsCache(): GraphicsStorage; + refreshCollections(): void; + }; + +const protocol: ExtensionMessenger = defineExtensionMessaging(); + +export const onMessage = protocol.onMessage; + +export const sendMessage: ExtensionMessenger["sendMessage"] = async (...args) => +{ + try + { + return await protocol.sendMessage(...args); + } + catch (ex) + { + console.error(ex); + return undefined!; + } +}; diff --git a/utils/saveTabsToCollection.ts b/utils/saveTabsToCollection.ts new file mode 100644 index 0000000..9461ac9 --- /dev/null +++ b/utils/saveTabsToCollection.ts @@ -0,0 +1,134 @@ +import { CollectionItem, GroupItem } from "@/models/CollectionModels"; +import { Tabs } from "wxt/browser"; +import { settings } from "./settings"; +import sendNotification from "./sendNotification"; + +export default async function saveTabsToCollection(closeTabs: boolean): Promise +{ + let tabs: Tabs.Tab[] = await browser.tabs.query({ + currentWindow: true, + highlighted: true + }); + + if (tabs.length < 2) + { + const ignorePinned: boolean = await settings.ignorePinned.getValue(); + tabs = await browser.tabs.query({ + currentWindow: true, + pinned: ignorePinned ? false : undefined + }); + } + + const [collection, tabsToClose] = await createCollectionFromTabs(tabs); + + if (closeTabs) + await browser.tabs.remove(tabsToClose.map(i => i.id!)); + + return collection; +} + +async function createCollectionFromTabs(tabs: Tabs.Tab[]): Promise<[CollectionItem, Tabs.Tab[]]> +{ + if (tabs.length < 1) + return [{ type: "collection", timestamp: Date.now(), items: [] }, []]; + + const tabCount: number = tabs.length; + + tabs = tabs.filter(i => + i.url && + !i.url.startsWith(browser.runtime.getURL("/")) && + new URL(i.url).protocol !== "about:" && + new URL(i.url).hostname !== "newtab" + ); + + const collection: CollectionItem = { + type: "collection", + timestamp: Date.now(), + items: [] + }; + + let tabIndex: number = 0; + + if (tabs[tabIndex].pinned) + { + collection.items.push({ type: "group", pinned: true, items: [] }); + + for (; tabIndex < tabs.length; tabIndex++) + { + if (!tabs[tabIndex].pinned) + break; + + (collection.items[0] as GroupItem).items.push({ + type: "tab", + url: tabs[tabIndex].url!, + title: tabs[tabIndex].title + }); + } + } + + if (import.meta.env.FIREFOX) + { + for (; tabIndex < tabs.length; tabIndex++) + collection.items.push({ type: "tab", url: tabs[tabIndex].url!, title: tabs[tabIndex].title }); + + return [collection, tabs]; + } + + // Special case, if all tabs are in the same group, create a collection with the group title + if (tabs[0].groupId && tabs[0].groupId !== chrome.tabGroups.TAB_GROUP_ID_NONE && + tabs.every(i => i.groupId === tabs[0].groupId) + ) + { + const group = await browser.tabGroups!.get(tabs[0].groupId); + collection.title = group.title; + collection.color = group.color; + + tabs.forEach(i => + collection.items.push({ type: "tab", url: i.url!, title: i.title }) + ); + + return [collection, tabs]; + } + + let activeGroup: number | null = null; + + for (; tabIndex < tabs.length; tabIndex++) + { + const tab = tabs[tabIndex]; + + if (!tab.groupId || tab.groupId === chrome.tabGroups.TAB_GROUP_ID_NONE) + { + collection.items.push({ type: "tab", url: tab.url!, title: tab.title }); + activeGroup = null; + continue; + } + + if (!activeGroup || activeGroup !== tab.groupId) + { + activeGroup = tab.groupId; + const group = await browser.tabGroups!.get(activeGroup); + + collection.items.push({ + type: "group", + color: group.color, + title: group.title, + items: [] + }); + } + + (collection.items[collection.items.length - 1] as GroupItem).items.push({ + type: "tab", + url: tab.url!, + title: tab.title + }); + } + + if (tabs.length < tabCount) + await sendNotification({ + title: i18n.t("notifications.partial_save.title"), + message: i18n.t("notifications.partial_save.message"), + icon: "/notification_icons/save_warning.png" + }); + + return [collection, tabs]; +} diff --git a/utils/sendNotification.ts b/utils/sendNotification.ts new file mode 100644 index 0000000..40d35dc --- /dev/null +++ b/utils/sendNotification.ts @@ -0,0 +1,26 @@ +import { PublicPath } from "wxt/browser"; + +export default async function sendNotification(props: NotificationProps): Promise +{ + try + { + await browser.notifications.create({ + type: "basic", + title: props.title, + message: props.message, + iconUrl: browser.runtime.getURL(props.icon) + }); + } + catch (ex) + { + console.error("Error while showing cloud error notification (probably because of user restrictions)"); + console.error(ex); + } +} + +export type NotificationProps = + { + title: string; + message: string; + icon: PublicPath; + }; diff --git a/utils/settings.tsx b/utils/settings.tsx new file mode 100644 index 0000000..eb4753e --- /dev/null +++ b/utils/settings.tsx @@ -0,0 +1,99 @@ +import { CollectionSortMode } from "@/entrypoints/sidepanel/utils/sortCollections"; + +export const settings = { + defaultRestoreAction: storage.defineItem<"open" | "restore">( + "sync:defaultRestoreAction", + { + fallback: "open", + version: 1 + } + ), + + defaultSaveAction: storage.defineItem<"save" | "set_aside">( + "sync:defaultSaveAction", + { + fallback: "set_aside", + version: 1 + } + ), + + dismissOnLoad: storage.defineItem( + "sync:dismissOnLoad", + { + fallback: false, + version: 1 + } + ), + + deletePrompt: storage.defineItem( + "sync:deletePrompt", + { + fallback: true, + version: 1 + } + ), + + tilesView: storage.defineItem( + "sync:tilesView", + { + fallback: true, + version: 1 + } + ), + + sortMode: storage.defineItem( + "sync:sortMode", + { + fallback: "custom", + version: 1 + } + ), + + ignorePinned: storage.defineItem( + "sync:ignorePinned", + { + fallback: true, + version: 1 + } + ), + + alwaysShowToolbars: storage.defineItem( + "sync:alwaysShowToolbars", + { + fallback: false, + version: 1 + } + ), + + showBadge: storage.defineItem( + "sync:showBadge", + { + fallback: true, + version: 1 + } + ), + + contextAction: storage.defineItem<"action" | "context" | "open">( + "sync:contextAction", + { + fallback: "open", + version: 1 + } + ), + + listLocation: storage.defineItem<"sidebar" | "popup" | "tab" | "pinned">( + "sync:listLocation", + { + fallback: "sidebar", + version: 1 + } + ), + + notifyOnSave: storage.defineItem( + "sync:notifyOnSave", + { + fallback: true, + version: 1 + } + ) +}; diff --git a/utils/watchTabSelection.ts b/utils/watchTabSelection.ts new file mode 100644 index 0000000..20e95a4 --- /dev/null +++ b/utils/watchTabSelection.ts @@ -0,0 +1,20 @@ +import { Unwatch } from "wxt/storage"; + +export default function watchTabSelection(onChange: TabSelectChangeHandler): Unwatch +{ + const handleTabSelection = async () => + { + const highlightedTabs = await browser.tabs.query({ + currentWindow: true, + highlighted: true + }); + onChange(highlightedTabs.length > 1 ? "selected" : "all"); + }; + + handleTabSelection(); + browser.tabs.onHighlighted.addListener(handleTabSelection); + + return () => browser.tabs.onHighlighted.removeListener(handleTabSelection); +} + +export type TabSelectChangeHandler = (selection: "all" | "selected") => void; diff --git a/web-ext.config.js b/web-ext.config.js new file mode 100644 index 0000000..3ae7115 --- /dev/null +++ b/web-ext.config.js @@ -0,0 +1,11 @@ +import { defineRunnerConfig } from "wxt"; + +export default defineRunnerConfig({ + binaries: + { + edge: "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe" + }, + chromiumArgs: [ + "--lang=en-US" + ] +}); diff --git a/wxt.config.ts b/wxt.config.ts new file mode 100644 index 0000000..a413367 --- /dev/null +++ b/wxt.config.ts @@ -0,0 +1,89 @@ +import { ConfigEnv, defineConfig, UserManifest } from "wxt"; + +// See https://wxt.dev/api/config.html +export default defineConfig({ + modules: ["@wxt-dev/module-react", "@wxt-dev/i18n/module"], + imports: { + dirsScanOptions: + { + // Disable auto-imports for project's files + fileFilter: () => false + } + }, + + manifest: ({ browser }: ConfigEnv) => + { + const manifest: UserManifest = { + name: "__MSG_manifest_name__", + description: "__MSG_manifest_description__", + homepage_url: "https://github.com/xfox111/TabsAsideExtension/", + + action: { + default_title: "__MSG_manifest_name__" + }, + + default_locale: "en", + permissions: + [ + "storage", + "unlimitedStorage", + "tabs", + "notifications", + "contextMenus", + "bookmarks" + ], + + commands: + { + show_collections: + { + suggested_key: + { + default: "Alt+P", + mac: "MacCtrl+P" + }, + description: "__MSG_shortcuts_toggle_sidebar__" + }, + set_aside: { + suggested_key: + { + default: "Alt+T", + mac: "MacCtrl+T" + }, + description: "__MSG_shortcuts_set_aside__" + }, + save: + { + suggested_key: + { + default: "Alt+U", + mac: "MacCtrl+U" + }, + description: "__MSG_shortcuts_save_tabs__" + } + }, + + host_permissions: [""] + }; + + if (browser === "firefox") + { + manifest.browser_specific_settings = { + gecko: + { + id: "tabs-aside@xfox111.net", + strict_min_version: "109.0" + } + }; + + // @ts-expect-error author key in Firefox has a different format + manifest.author = "__MSG_manifest_author__"; + } + else + { + manifest.permissions!.push("tabGroups"); + } + + return manifest; + } +}); diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..81296f7 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,6889 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@1natsu/wait-element@^4.1.2": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@1natsu/wait-element/-/wait-element-4.1.2.tgz#f18b031dc9fb4ac22e114ed04daeef1fbde2217f" + integrity sha512-qWxSJD+Q5b8bKOvESFifvfZ92DuMsY+03SBNjTO34ipJLP6mZ9yK4bQz/vlh48aEQXoJfaZBqUwKL5BdI5iiWw== + dependencies: + defu "^6.1.4" + many-keys-map "^2.0.1" + +"@aklinker1/rollup-plugin-visualizer@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@aklinker1/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.12.0.tgz#259d7ab48248eaea6439b7b281a5d1b262c21bb6" + integrity sha512-X24LvEGw6UFmy0lpGJDmXsMyBD58XmX1bbwsaMLhNoM+UMQfQ3b2RtC+nz4b/NoRK5r6QJSKJHBNVeUdwqybaQ== + dependencies: + open "^8.4.0" + picomatch "^2.3.1" + source-map "^0.7.4" + yargs "^17.5.1" + +"@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@babel/code-frame@^7.21.4", "@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/compat-data@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.27.1.tgz#db7cf122745e0a332c44e847ddc4f5e5221a43f6" + integrity sha512-Q+E+rd/yBzNQhXkG+zQnF58e4zoZfBedaxwzPmicKsiK3nt8iJYrSrDbjwFFDGC4f+rPafqRaPH6TsDoSvMf7A== + +"@babel/core@^7.26.10": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.27.1.tgz#89de51e86bd12246003e3524704c49541b16c3e6" + integrity sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.27.1" + "@babel/helper-compilation-targets" "^7.27.1" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helpers" "^7.27.1" + "@babel/parser" "^7.27.1" + "@babel/template" "^7.27.1" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.1.tgz#862d4fad858f7208edd487c28b58144036b76230" + integrity sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w== + dependencies: + "@babel/parser" "^7.27.1" + "@babel/types" "^7.27.1" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + +"@babel/helper-compilation-targets@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.1.tgz#eac1096c7374f161e4f33fc8ae38f4ddf122087a" + integrity sha512-2YaDd/Rd9E598B5+WIc8wJPmWETiiJXFYVE60oX8FDohv7rAUU3CQj+A1MgeEmcsk2+dQuEjIe/GDvig0SqL4g== + dependencies: + "@babel/compat-data" "^7.27.1" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-module-imports@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" + integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/helper-module-transforms@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz#e1663b8b71d2de948da5c4fb2a20ca4f3ec27a6f" + integrity sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g== + dependencies: + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.27.1" + +"@babel/helper-plugin-utils@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" + integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/helpers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.1.tgz#ffc27013038607cdba3288e692c3611c06a18aa4" + integrity sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ== + dependencies: + "@babel/template" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.25.4", "@babel/parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.1.tgz#c55d5bed74449d1223701f1869b9ee345cc94cc9" + integrity sha512-I0dZ3ZpCrJ1c04OqlNsQcKiZlsrXf/kkE4FXzID9rIOYICsAbA8mMDzhW/luRNAHdCNt7os/u8wenklZDlUVUQ== + dependencies: + "@babel/types" "^7.27.1" + +"@babel/plugin-transform-react-jsx-self@^7.25.9": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz#af678d8506acf52c577cac73ff7fe6615c85fc92" + integrity sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-react-jsx-source@^7.25.9": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz#dcfe2c24094bb757bf73960374e7c55e434f19f0" + integrity sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/runtime@7.27.0": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.0.tgz#fbee7cf97c709518ecc1f590984481d5460d4762" + integrity sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/runtime@^7.1.2", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.1.tgz#9fce313d12c9a77507f264de74626e87fd0dc541" + integrity sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog== + +"@babel/template@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.1.tgz#b9e4f55c17a92312774dfbdde1b3c01c547bbae2" + integrity sha512-Fyo3ghWMqkHHpHQCoBs2VnYjR4iWFFjguTDEqA5WgZDOrFesVjMhMM2FSqTKSoUSDO1VQtavj8NFpdRBEvJTtg== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/traverse@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.1.tgz#4db772902b133bbddd1c4f7a7ee47761c1b9f291" + integrity sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.27.1" + "@babel/parser" "^7.27.1" + "@babel/template" "^7.27.1" + "@babel/types" "^7.27.1" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.25.4", "@babel/types@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.1.tgz#9defc53c16fc899e46941fc6901a9eea1c9d8560" + integrity sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + +"@ctrl/tinycolor@^3.3.4": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz#b6c75a56a1947cc916ea058772d666a2c8932f31" + integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA== + +"@devicefarmer/adbkit-logcat@^2.1.2": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@devicefarmer/adbkit-logcat/-/adbkit-logcat-2.1.3.tgz#c7a1fb58e500f5799711f32906a2210c0d1ac5ac" + integrity sha512-yeaGFjNBc/6+svbDeul1tNHtNChw6h8pSHAt5D+JsedUrMTN7tla7B15WLDyekxsuS2XlZHRxpuC6m92wiwCNw== + +"@devicefarmer/adbkit-monkey@~1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@devicefarmer/adbkit-monkey/-/adbkit-monkey-1.2.1.tgz#28cd6a121c5d572588081dd1c53454c604eef241" + integrity sha512-ZzZY/b66W2Jd6NHbAhLyDWOEIBWC11VizGFk7Wx7M61JZRz7HR9Cq5P+65RKWUU7u6wgsE8Lmh9nE4Mz+U2eTg== + +"@devicefarmer/adbkit@3.3.8": + version "3.3.8" + resolved "https://registry.yarnpkg.com/@devicefarmer/adbkit/-/adbkit-3.3.8.tgz#04bc35cb3a2d7385f2e22de40f54162088083183" + integrity sha512-7rBLLzWQnBwutH2WZ0EWUkQdihqrnLYCUMaB44hSol9e0/cdIhuNFcqZO0xNheAU6qqHVA8sMiLofkYTgb+lmw== + dependencies: + "@devicefarmer/adbkit-logcat" "^2.1.2" + "@devicefarmer/adbkit-monkey" "~1.2.1" + bluebird "~3.7" + commander "^9.1.0" + debug "~4.3.1" + node-forge "^1.3.1" + split "~1.0.1" + +"@dnd-kit/accessibility@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz#3b4202bd6bb370a0730f6734867785919beac6af" + integrity sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw== + dependencies: + tslib "^2.0.0" + +"@dnd-kit/core@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@dnd-kit/core/-/core-6.3.1.tgz#4c36406a62c7baac499726f899935f93f0e6d003" + integrity sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ== + dependencies: + "@dnd-kit/accessibility" "^3.1.1" + "@dnd-kit/utilities" "^3.2.2" + tslib "^2.0.0" + +"@dnd-kit/modifiers@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@dnd-kit/modifiers/-/modifiers-9.0.0.tgz#96a0280c77b10c716ef79d9792ce7ad04370771d" + integrity sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw== + dependencies: + "@dnd-kit/utilities" "^3.2.2" + tslib "^2.0.0" + +"@dnd-kit/sortable@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@dnd-kit/sortable/-/sortable-10.0.0.tgz#1f9382b90d835cd5c65d92824fa9dafb78c4c3e8" + integrity sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg== + dependencies: + "@dnd-kit/utilities" "^3.2.2" + tslib "^2.0.0" + +"@dnd-kit/utilities@^3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@dnd-kit/utilities/-/utilities-3.2.2.tgz#5a32b6af356dc5f74d61b37d6f7129a4040ced7b" + integrity sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg== + dependencies: + tslib "^2.0.0" + +"@emotion/hash@^0.9.0": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b" + integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g== + +"@esbuild/aix-ppc64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz#014180d9a149cffd95aaeead37179433f5ea5437" + integrity sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ== + +"@esbuild/android-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz#649e47e04ddb24a27dc05c395724bc5f4c55cbfe" + integrity sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ== + +"@esbuild/android-arm@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.3.tgz#8a0f719c8dc28a4a6567ef7328c36ea85f568ff4" + integrity sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A== + +"@esbuild/android-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.3.tgz#e2ab182d1fd06da9bef0784a13c28a7602d78009" + integrity sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ== + +"@esbuild/darwin-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz#c7f3166fcece4d158a73dcfe71b2672ca0b1668b" + integrity sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w== + +"@esbuild/darwin-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz#d8c5342ec1a4bf4b1915643dfe031ba4b173a87a" + integrity sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A== + +"@esbuild/freebsd-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz#9f7d789e2eb7747d4868817417cc968ffa84f35b" + integrity sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw== + +"@esbuild/freebsd-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz#8ad35c51d084184a8e9e76bb4356e95350a64709" + integrity sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q== + +"@esbuild/linux-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz#3af0da3d9186092a9edd4e28fa342f57d9e3cd30" + integrity sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A== + +"@esbuild/linux-arm@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz#e91cafa95e4474b3ae3d54da12e006b782e57225" + integrity sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ== + +"@esbuild/linux-ia32@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz#81025732d85b68ee510161b94acdf7e3007ea177" + integrity sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw== + +"@esbuild/linux-loong64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz#3c744e4c8d5e1148cbe60a71a11b58ed8ee5deb8" + integrity sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g== + +"@esbuild/linux-mips64el@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz#1dfe2a5d63702db9034cc6b10b3087cc0424ec26" + integrity sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag== + +"@esbuild/linux-ppc64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz#2e85d9764c04a1ebb346dc0813ea05952c9a5c56" + integrity sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg== + +"@esbuild/linux-riscv64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz#a9ea3334556b09f85ccbfead58c803d305092415" + integrity sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA== + +"@esbuild/linux-s390x@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz#f6a7cb67969222b200974de58f105dfe8e99448d" + integrity sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ== + +"@esbuild/linux-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz#a237d3578ecdd184a3066b1f425e314ade0f8033" + integrity sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA== + +"@esbuild/netbsd-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz#4c15c68d8149614ddb6a56f9c85ae62ccca08259" + integrity sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA== + +"@esbuild/netbsd-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz#12f6856f8c54c2d7d0a8a64a9711c01a743878d5" + integrity sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g== + +"@esbuild/openbsd-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz#ca078dad4a34df192c60233b058db2ca3d94bc5c" + integrity sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ== + +"@esbuild/openbsd-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz#c9178adb60e140e03a881d0791248489c79f95b2" + integrity sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w== + +"@esbuild/sunos-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz#03765eb6d4214ff27e5230af779e80790d1ee09f" + integrity sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA== + +"@esbuild/win32-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz#f1c867bd1730a9b8dfc461785ec6462e349411ea" + integrity sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ== + +"@esbuild/win32-ia32@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz#77491f59ef6c9ddf41df70670d5678beb3acc322" + integrity sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew== + +"@esbuild/win32-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz#b17a2171f9074df9e91bfb07ef99a892ac06412a" + integrity sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg== + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a" + integrity sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + +"@eslint/config-array@^0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.20.0.tgz#7a1232e82376712d3340012a2f561a2764d1988f" + integrity sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ== + dependencies: + "@eslint/object-schema" "^2.1.6" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/config-helpers@^0.2.1": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.2.2.tgz#3779f76b894de3a8ec4763b79660e6d54d5b1010" + integrity sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg== + +"@eslint/core@^0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.12.0.tgz#5f960c3d57728be9f6c65bd84aa6aa613078798e" + integrity sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/core@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.13.0.tgz#bf02f209846d3bf996f9e8009db62df2739b458c" + integrity sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/css-tree@^3.3.3": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@eslint/css-tree/-/css-tree-3.5.0.tgz#23a9cc7759893e84178418390a02646f4d2e6ce5" + integrity sha512-RtpdRxIq6AVf078nY0oqZ+x5UTzuxdt/Q2n3RmA4mcfTQVtsvdoIvOxo+4qikydlr6WskqIIofXc5KeGwTYLeg== + dependencies: + mdn-data "2.20.0" + source-map-js "^1.0.1" + +"@eslint/css@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@eslint/css/-/css-0.7.0.tgz#e864fb73334fefef3385e28832ce9f3ae846d034" + integrity sha512-d6mo8etv4igrTGxgvWSgA5+TsppfObM/Xhlu8JWbkqNBiaJXztUNH45R1B4i1GL2PNIFMLREI3Kh9lTBi19l7g== + dependencies: + "@eslint/core" "^0.13.0" + "@eslint/css-tree" "^3.3.3" + "@eslint/plugin-kit" "^0.2.5" + +"@eslint/eslintrc@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.1.tgz#e55f7f1dd400600dd066dbba349c4c0bac916964" + integrity sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ== + 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.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.26.0", "@eslint/js@^9.26.0": + version "9.26.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.26.0.tgz#1e13126b67a3db15111d2dcc61f69a2acff70bd5" + integrity sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ== + +"@eslint/json@^0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@eslint/json/-/json-0.12.0.tgz#7d1cb7152d01f3837703c154a5b38233f409395e" + integrity sha512-n/7dz8HFStpEe4o5eYk0tdkBdGUS/ZGb0GQCeDWN1ZmRq67HMHK4vC33b0rQlTT6xdZoX935P4vstiWVk5Ying== + dependencies: + "@eslint/core" "^0.12.0" + "@eslint/plugin-kit" "^0.2.7" + "@humanwhocodes/momoa" "^3.3.4" + natural-compare "^1.4.0" + +"@eslint/object-schema@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" + integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== + +"@eslint/plugin-kit@^0.2.5", "@eslint/plugin-kit@^0.2.7", "@eslint/plugin-kit@^0.2.8": + version "0.2.8" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz#47488d8f8171b5d4613e833313f3ce708e3525f8" + integrity sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA== + dependencies: + "@eslint/core" "^0.13.0" + levn "^0.4.1" + +"@floating-ui/core@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.7.0.tgz#1aff27a993ea1b254a586318c29c3b16ea0f4d0a" + integrity sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA== + dependencies: + "@floating-ui/utils" "^0.2.9" + +"@floating-ui/devtools@0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@floating-ui/devtools/-/devtools-0.2.1.tgz#3e8023e09ede273a7aa426e7911f3dac630024c5" + integrity sha512-8PHJLbD6VhBh+LJ1uty/Bz30qs02NXCE5u8WpOhSewlYXUWl03GNXknr9AS2yaAWJEQaY27x7eByJs44gODBcw== + +"@floating-ui/dom@^1.6.12": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.7.0.tgz#f9f83ee4fee78ac23ad9e65b128fc11a27857532" + integrity sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg== + dependencies: + "@floating-ui/core" "^1.7.0" + "@floating-ui/utils" "^0.2.9" + +"@floating-ui/utils@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429" + integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg== + +"@fluentui/keyboard-keys@^9.0.8": + version "9.0.8" + resolved "https://registry.yarnpkg.com/@fluentui/keyboard-keys/-/keyboard-keys-9.0.8.tgz#812b923f20d428f3c5cdff9922a4478b59e907c5" + integrity sha512-iUSJUUHAyTosnXK8O2Ilbfxma+ZyZPMua5vB028Ys96z80v+LFwntoehlFsdH3rMuPsA8GaC1RE7LMezwPBPdw== + dependencies: + "@swc/helpers" "^0.5.1" + +"@fluentui/priority-overflow@^9.1.15": + version "9.1.15" + resolved "https://registry.yarnpkg.com/@fluentui/priority-overflow/-/priority-overflow-9.1.15.tgz#edce236aa21024ead00dbf6e7c5e4eaa89cd6a1d" + integrity sha512-/3jPBBq64hRdA416grVj+ZeMBUIaKZk2S5HiRg7CKCAV1JuyF84Do0rQI6ns8Vb9XOGuc4kurMcL/UEftoEVrg== + dependencies: + "@swc/helpers" "^0.5.1" + +"@fluentui/react-accordion@^9.6.8": + version "9.6.8" + resolved "https://registry.yarnpkg.com/@fluentui/react-accordion/-/react-accordion-9.6.8.tgz#b11d8823aed71176ab5147dcc3ef5a96c5255f4b" + integrity sha512-KE3YNGPTsN7tbnAfgbs7THAFfURj+yvO2GgEIVr++2xTgHXR7GEwM7RrbE1ZbJZM7gbeGE5rCg006OBfE4qbuQ== + dependencies: + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-motion" "^9.7.2" + "@fluentui/react-motion-components-preview" "^0.4.9" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-alert@9.0.0-beta.124": + version "9.0.0-beta.124" + resolved "https://registry.yarnpkg.com/@fluentui/react-alert/-/react-alert-9.0.0-beta.124.tgz#b408971fd5b1e76bdca20fcae280a527858ad2f5" + integrity sha512-yFBo3B5H9hnoaXxlkuz8wRz04DEyQ+ElYA/p5p+Vojf19Zuta8DmFZZ6JtWdtxcdnnQ4LvAfC5OYYlzdReozPA== + dependencies: + "@fluentui/react-avatar" "^9.6.29" + "@fluentui/react-button" "^9.3.83" + "@fluentui/react-icons" "^2.0.239" + "@fluentui/react-jsx-runtime" "^9.0.39" + "@fluentui/react-tabster" "^9.21.5" + "@fluentui/react-theme" "^9.1.19" + "@fluentui/react-utilities" "^9.18.10" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-aria@^9.14.6": + version "9.14.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-aria/-/react-aria-9.14.6.tgz#b6799e991bcd393d62744ec7b668a2587adf79b9" + integrity sha512-3vaEzujXdQxhYFzRXnkDNDImbMS0FXa8pq9WPo0JiKThsQp1QQQzdQbFsY7vfHd9aWjjWyCrRDMH25H37ZZ06w== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-utilities" "^9.19.0" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-avatar@^9.6.29", "@fluentui/react-avatar@^9.7.6": + version "9.7.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-avatar/-/react-avatar-9.7.6.tgz#b7b86388c61accce987edee8b00e1bf4b5b7d52a" + integrity sha512-T4W+CaGjdkWgfiI7Me+wtFj2ewZFH+GpZbSexatqDjoq5ywrFOZf+aADtaHuocHcH7hx/U3AXMvTTQyzoDMuRg== + dependencies: + "@fluentui/react-badge" "^9.2.54" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-popover" "^9.10.6" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-tooltip" "^9.6.6" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-badge@^9.2.54": + version "9.2.54" + resolved "https://registry.yarnpkg.com/@fluentui/react-badge/-/react-badge-9.2.54.tgz#63b7d0065a2fe535296f81f95c63bd255b56d048" + integrity sha512-2PU0UA0VDz/XwbYKmMmPQKg4ykYHoUsgs3oZIqdwMPM3zxuhclsFEFx2xj4nxpMKiGCTBSBTM0fdOEQwRrbluQ== + dependencies: + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-breadcrumb@^9.1.6": + version "9.1.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-breadcrumb/-/react-breadcrumb-9.1.6.tgz#deca150702603a8bba90400946f7d2c54923d797" + integrity sha512-61oH9e/6kBRhnDeSStWe0AMS/9I9nkSzTFEKHEWJDnZYPFIhvlzn56TcAtuzVUYgHV1Jsk5PRLd9aQtJL1ENYw== + dependencies: + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-button" "^9.4.6" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-link" "^9.4.6" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-button@^9.3.83", "@fluentui/react-button@^9.4.6": + version "9.4.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-button/-/react-button-9.4.6.tgz#27151615a8d498bafeedae518bce66ae94570150" + integrity sha512-1G92nGpWOYQ7vR+3g0Y0RLeAlqpZnpHVhXpQG504+yDGIAsn76I1zt+XcD9/2uaDmoH4tXiHS1SPtShujYVXjA== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-card@^9.2.5": + version "9.2.5" + resolved "https://registry.yarnpkg.com/@fluentui/react-card/-/react-card-9.2.5.tgz#05a60b5cd84ba8d5f9cfe5feac2818ca61d44d28" + integrity sha512-ODgwhKt+GL0TbLLRb3kHuf4ftCdcat3uNdN6mcVrqsL3+elJONvd7OA02jFbU/WFVR3IKOx6dUjRYNQYol0CiA== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-text" "^9.4.36" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-carousel@^9.6.6": + version "9.6.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-carousel/-/react-carousel-9.6.6.tgz#ce0f3fbd6662bada5021b5e65b613e8b3f22bbb4" + integrity sha512-/08DyIdg+wn72D+ShnOUQXHqMgAsFUIlCMmyBvNlMImFIDxE6NjVXy+5Yes5mpsJYGWetmCAcECf+SQdgDsU1w== + dependencies: + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-button" "^9.4.6" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-tooltip" "^9.6.6" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + embla-carousel "^8.5.1" + embla-carousel-autoplay "^8.5.1" + embla-carousel-fade "^8.5.1" + +"@fluentui/react-checkbox@^9.3.6": + version "9.3.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-checkbox/-/react-checkbox-9.3.6.tgz#bfb4af78cef5ec260f088bc0af008d785a385e55" + integrity sha512-70HiPwnR5Ed59bulKs733xTFtm9JHQCJlaJc+l9LR6jpiZucvMqNGDfpYDqvFTbCm+FCrvo6gxmKfADAHxANWw== + dependencies: + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-label" "^9.1.87" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-color-picker@^9.0.4": + version "9.0.4" + resolved "https://registry.yarnpkg.com/@fluentui/react-color-picker/-/react-color-picker-9.0.4.tgz#70418e9584efe01663a3cfbd797ae0cb321af906" + integrity sha512-srbVlDDo3iRcjBMH55MPKiDchIN9SWwZfvE4gpJ1PE80Bs8Frjzk1m1iRO7ZkEtedhEqvVzaWYN5BvAQE8S5qg== + dependencies: + "@ctrl/tinycolor" "^3.3.4" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-combobox@^9.14.6": + version "9.14.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-combobox/-/react-combobox-9.14.6.tgz#d7c71c6da046ecd3c0631d6ebcbd08dd425cf5dc" + integrity sha512-JGkc5wW+NNlMs1P+UIMLWCzYux5SMgFMLjXuXEFP52hX8ka9Nk7l8WSTW58LRsccT5Mf6JXDiSs4CK5D6VXBOA== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-portal" "^9.5.6" + "@fluentui/react-positioning" "^9.16.7" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-components@^9.63.0": + version "9.63.0" + resolved "https://registry.yarnpkg.com/@fluentui/react-components/-/react-components-9.63.0.tgz#7a65d222df0450cc447c2b72296e4ba4466fa002" + integrity sha512-2Wka+gKv70FbSWp/FUASfNZ4QctBUIl87O44B41VEcX7/ucOsHhF4yVB4KS8dgxnkL30M9mX8COu5c2bORDq4A== + dependencies: + "@fluentui/react-accordion" "^9.6.8" + "@fluentui/react-alert" "9.0.0-beta.124" + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-avatar" "^9.7.6" + "@fluentui/react-badge" "^9.2.54" + "@fluentui/react-breadcrumb" "^9.1.6" + "@fluentui/react-button" "^9.4.6" + "@fluentui/react-card" "^9.2.5" + "@fluentui/react-carousel" "^9.6.6" + "@fluentui/react-checkbox" "^9.3.6" + "@fluentui/react-color-picker" "^9.0.4" + "@fluentui/react-combobox" "^9.14.6" + "@fluentui/react-dialog" "^9.12.8" + "@fluentui/react-divider" "^9.2.86" + "@fluentui/react-drawer" "^9.7.8" + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-image" "^9.1.84" + "@fluentui/react-infobutton" "9.0.0-beta.102" + "@fluentui/react-infolabel" "^9.2.0" + "@fluentui/react-input" "^9.5.6" + "@fluentui/react-label" "^9.1.87" + "@fluentui/react-link" "^9.4.6" + "@fluentui/react-list" "^9.1.6" + "@fluentui/react-menu" "^9.16.6" + "@fluentui/react-message-bar" "^9.4.7" + "@fluentui/react-motion" "^9.7.2" + "@fluentui/react-overflow" "^9.3.6" + "@fluentui/react-persona" "^9.3.6" + "@fluentui/react-popover" "^9.10.6" + "@fluentui/react-portal" "^9.5.6" + "@fluentui/react-positioning" "^9.16.7" + "@fluentui/react-progress" "^9.2.6" + "@fluentui/react-provider" "^9.20.6" + "@fluentui/react-radio" "^9.3.6" + "@fluentui/react-rating" "^9.1.6" + "@fluentui/react-search" "^9.1.6" + "@fluentui/react-select" "^9.2.6" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-skeleton" "^9.2.6" + "@fluentui/react-slider" "^9.3.7" + "@fluentui/react-spinbutton" "^9.3.6" + "@fluentui/react-spinner" "^9.5.11" + "@fluentui/react-swatch-picker" "^9.2.6" + "@fluentui/react-switch" "^9.2.6" + "@fluentui/react-table" "^9.16.6" + "@fluentui/react-tabs" "^9.7.6" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-tag-picker" "^9.5.6" + "@fluentui/react-tags" "^9.5.4" + "@fluentui/react-teaching-popover" "^9.4.5" + "@fluentui/react-text" "^9.4.36" + "@fluentui/react-textarea" "^9.4.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-toast" "^9.4.8" + "@fluentui/react-toolbar" "^9.4.5" + "@fluentui/react-tooltip" "^9.6.6" + "@fluentui/react-tree" "^9.10.9" + "@fluentui/react-utilities" "^9.19.0" + "@fluentui/react-virtualizer" "9.0.0-alpha.96" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-context-selector@^9.1.76": + version "9.1.76" + resolved "https://registry.yarnpkg.com/@fluentui/react-context-selector/-/react-context-selector-9.1.76.tgz#83541784a9d401de7034123709f6bfb2fa368421" + integrity sha512-GmkHiLuMBzYOVvPkXNhMJTusx9hf43+VizFjAhSfZWOnNwLjiekjDocs7S2XD0f3MmcVx+aB2tRdTDHxGAF/1A== + dependencies: + "@fluentui/react-utilities" "^9.19.0" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-dialog@^9.12.8": + version "9.12.8" + resolved "https://registry.yarnpkg.com/@fluentui/react-dialog/-/react-dialog-9.12.8.tgz#a81c7eecec3930c9011c9a67088b8de3c0b5e392" + integrity sha512-bfZehsH5ejXc8qO5SZdu50siusz3VhpP1imCVSz92cwsyowjOaGX8DAjfbvb+QfNT/0RYqqdveCXTLPVC7SFWQ== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-motion" "^9.7.2" + "@fluentui/react-motion-components-preview" "^0.4.9" + "@fluentui/react-portal" "^9.5.6" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-divider@^9.2.86": + version "9.2.86" + resolved "https://registry.yarnpkg.com/@fluentui/react-divider/-/react-divider-9.2.86.tgz#696ed355c23156b2e63025dfa8e499a62f59e40e" + integrity sha512-8hzwDVdW7CkumW8XU16lsrrg6s0tNAIWdsFC4Utfb/BL2xgfJRdg/0q6Dzw12uhQHtssC3pKNQV0mp4ia0oqww== + dependencies: + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-drawer@^9.7.8": + version "9.7.8" + resolved "https://registry.yarnpkg.com/@fluentui/react-drawer/-/react-drawer-9.7.8.tgz#f9f409214924fa38176aa39412682ff2a89c5f11" + integrity sha512-s9epUHmw/MrkVEpjzZJcdwjYSx2dVM7Uf9deHA//+dgHCM0Yybmn6vWJ+OArNkzdpYHLBuG3Cwk07tnQqGJx2Q== + dependencies: + "@fluentui/react-dialog" "^9.12.8" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-motion" "^9.7.2" + "@fluentui/react-portal" "^9.5.6" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-field@^9.2.6": + version "9.2.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-field/-/react-field-9.2.6.tgz#caffd4f7b18e686b8b59e2b20868684338272f60" + integrity sha512-C+x+96pRgpx1ib08krazPdYn7+lgD7kDGNlvadmUPM05Zm68Zm2mytMjZ/iy50N/iydozmbLG/i930LVUAF7/g== + dependencies: + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-label" "^9.1.87" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-icons@^2.0.237", "@fluentui/react-icons@^2.0.239", "@fluentui/react-icons@^2.0.245", "@fluentui/react-icons@^2.0.298": + version "2.0.298" + resolved "https://registry.yarnpkg.com/@fluentui/react-icons/-/react-icons-2.0.298.tgz#298e02796c460c1d3fc08c4e5fb8dafa1ed5be15" + integrity sha512-4bLyZsLtdpS1634ptlBQeoEDlsg//61s8Lp8RlM+TyBgXaIONS9KIlRiujlrGJyuksDujq2V+uEfpqAGrkAHtQ== + dependencies: + "@griffel/react" "^1.0.0" + tslib "^2.1.0" + +"@fluentui/react-image@^9.1.84": + version "9.1.84" + resolved "https://registry.yarnpkg.com/@fluentui/react-image/-/react-image-9.1.84.tgz#72aa5838485b9ec10ab4b675167b3d18b602f269" + integrity sha512-+8X9IPtNi+RLsSJEIODUfnnalPXLJpfqSyyjrVcm/xjEasCm77F1kMSzCGiHbFYvz7hq5g5I4B/OH4TjL+fcqg== + dependencies: + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-infobutton@9.0.0-beta.102": + version "9.0.0-beta.102" + resolved "https://registry.yarnpkg.com/@fluentui/react-infobutton/-/react-infobutton-9.0.0-beta.102.tgz#c0473275141999455fae4388f47d4f77b98c0f89" + integrity sha512-3kA4F0Vga8Ds6JGlBajLCCDOo/LmPuS786Wg7ui4ZTDYVIMzy1yp2XuVcZniifBFvEp0HQCUoDPWUV0VI3FfzQ== + dependencies: + "@fluentui/react-icons" "^2.0.237" + "@fluentui/react-jsx-runtime" "^9.0.36" + "@fluentui/react-label" "^9.1.68" + "@fluentui/react-popover" "^9.9.6" + "@fluentui/react-tabster" "^9.21.0" + "@fluentui/react-theme" "^9.1.19" + "@fluentui/react-utilities" "^9.18.7" + "@griffel/react" "^1.5.14" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-infolabel@^9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@fluentui/react-infolabel/-/react-infolabel-9.2.0.tgz#e0a9a19cf93cf7259014638f7ba92c0c9192f7c8" + integrity sha512-lNxcGj2kcpykdoOW9HSielq7o30RI2vI5LTy4pgd5OQ7/1ffik6+ioKPjylnIV6nIPgv035x4Pf/8s9B6m0+oA== + dependencies: + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-label" "^9.1.87" + "@fluentui/react-popover" "^9.10.6" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-input@^9.5.6": + version "9.5.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-input/-/react-input-9.5.6.tgz#563ac8f60d2ee9ea9d7635e8457f6a37dd2ea522" + integrity sha512-qegsdTawoewipYPYKfuYm21p5VZ59Yl33ofQiGoUgY03r/ddylHenWIOLdFyuUuPXBv2m/ESMCL1MZaiDUPDFg== + dependencies: + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-jsx-runtime@^9.0.36", "@fluentui/react-jsx-runtime@^9.0.39", "@fluentui/react-jsx-runtime@^9.0.54": + version "9.0.54" + resolved "https://registry.yarnpkg.com/@fluentui/react-jsx-runtime/-/react-jsx-runtime-9.0.54.tgz#2b2cf65b32e61486711343f6bb1468cdaa9da186" + integrity sha512-zSkP9X/bAFg17QUDBs4bnbDUgeQSpSBVbH4nKYa3cZb78vV3e3m3nyADBvb97NYkywyd7CfIXq8iTpDWVEoWTw== + dependencies: + "@fluentui/react-utilities" "^9.19.0" + "@swc/helpers" "^0.5.1" + react-is "^17.0.2" + +"@fluentui/react-label@^9.1.68", "@fluentui/react-label@^9.1.87": + version "9.1.87" + resolved "https://registry.yarnpkg.com/@fluentui/react-label/-/react-label-9.1.87.tgz#3de034d907360e86b837579db3c6c40730231870" + integrity sha512-vfUppmSWkpwXztHU21oGcduYQ9jldkPrFpl+/zWmbiOia5CKTMqJtHqLJMMe/W1uoNKqoNU37uVp3bZgIWUHJg== + dependencies: + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-link@^9.4.6": + version "9.4.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-link/-/react-link-9.4.6.tgz#19c8c5bcb9ae2733e7d4e632821aa1971cc620d8" + integrity sha512-PuOyp8JObLWzvUsK8PKjqITtwdcRxonEUxOztvv3HPAyE11EtgdvPKEhm5cQPmXN/EA/D2/Dk80PHLeNRzVaZQ== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-list@^9.1.6": + version "9.1.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-list/-/react-list-9.1.6.tgz#5ea7909f77771f0fbfc60ef7b016abc0d5dc0ac2" + integrity sha512-Sgl0wVQnJrKFRh4AERtB3eyJERDkSBhH4dGz+KaPaltItWe/0g2/VOqNSOk9oaG3rka7BYSeU6pLUf5AwkqMgA== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-checkbox" "^9.3.6" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-menu@^9.16.6": + version "9.16.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-menu/-/react-menu-9.16.6.tgz#b3ee9a020f7491c0851d3a68dcceab8bfddb799b" + integrity sha512-qiVoje/i8Pj0joZN/uaJd6r0H9qZTgjAEgsnJc32HEXQuX3HDGkxdxiCES+h24a8Alu09ELwVJAzdbWvedCqug== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-portal" "^9.5.6" + "@fluentui/react-positioning" "^9.16.7" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-message-bar@^9.4.7": + version "9.4.7" + resolved "https://registry.yarnpkg.com/@fluentui/react-message-bar/-/react-message-bar-9.4.7.tgz#111a33169950749c185f4629d6d5089255b69011" + integrity sha512-9XevlyC5Kr7oVBMo8Dd9ddw8Fmgq/yLN19zz+jyHzPGZMWU+BC40LM/w8l11WdgqN6ij5LZewq9pElMRMJIKkw== + dependencies: + "@fluentui/react-button" "^9.4.6" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-link" "^9.4.6" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + react-transition-group "^4.4.1" + +"@fluentui/react-motion-components-preview@^0.4.9": + version "0.4.9" + resolved "https://registry.yarnpkg.com/@fluentui/react-motion-components-preview/-/react-motion-components-preview-0.4.9.tgz#2b3c8647920ee421eb327548decdc294f24e51de" + integrity sha512-sMtCqgmPHclfo6EqeIZmtXqJt+1fJn0Bo7ORsayXRJvjrmf8buDFnCJCjzYPNUR3npy9GFedMqmIkC6ovKkV0w== + dependencies: + "@fluentui/react-motion" "*" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-motion@*", "@fluentui/react-motion@^9.7.2": + version "9.7.2" + resolved "https://registry.yarnpkg.com/@fluentui/react-motion/-/react-motion-9.7.2.tgz#fcd2c54082975b6c7f91de813e8efe8eb7daef13" + integrity sha512-xUDkTNPsXKZIlk+Xr+uozdEmKfZ3iNE7dXUAPOgX5rntdMS50JZf4ggyaKdSJsuOVQNqWAoEcCNYLISroDw07g== + dependencies: + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-utilities" "^9.19.0" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-overflow@^9.3.6": + version "9.3.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-overflow/-/react-overflow-9.3.6.tgz#f343a3a9fdefc9442f82aba6d9cb6789ef6b4ec6" + integrity sha512-yyYX+6jLDyWwZg2G3r4gTxziaT70U9pdRUO1oEVE6Sv1xvMsQGfRQth4khl6OihB1fAFv4mAyx7NTX94D8RYhw== + dependencies: + "@fluentui/priority-overflow" "^9.1.15" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-persona@^9.3.6": + version "9.3.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-persona/-/react-persona-9.3.6.tgz#672341e4e4f52aa09a7205f6c578fc27da310c80" + integrity sha512-EJZk6ZANrWoZ+lGvjW+xXuj5AGu5uNT6LiBo1H3SM6ug/eldz32Pa+UXYPU6sVEW0T8+wUCvPZmhgMnahELSew== + dependencies: + "@fluentui/react-avatar" "^9.7.6" + "@fluentui/react-badge" "^9.2.54" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-popover@^9.10.6", "@fluentui/react-popover@^9.9.6": + version "9.10.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-popover/-/react-popover-9.10.6.tgz#e8a82b6ee84bc3dfb1cbe92362bdf2fd635b31b6" + integrity sha512-ddYAbytBGukB2EgcjcMV7q7A8Yh6tmWk8Eg9m1O0rAnB/8xlkuG8BLAN98S4kAGsmrxX2GMb1R3NBBFr+yMdGA== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-portal" "^9.5.6" + "@fluentui/react-positioning" "^9.16.7" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-portal@^9.5.6": + version "9.5.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-portal/-/react-portal-9.5.6.tgz#6f9c70dddc23cb35f00deb9a0a2d502175c8dd7c" + integrity sha512-mAZ5sVf+2TiG5BKOo7Vv88+UeBZEeVGnTZcI6U2iggB7LLzPQdl3Bw+w8QUMBO9PHS/QtzliTqeGpt2QbtMyxw== + dependencies: + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + use-disposable "^1.0.1" + +"@fluentui/react-positioning@^9.16.7": + version "9.16.7" + resolved "https://registry.yarnpkg.com/@fluentui/react-positioning/-/react-positioning-9.16.7.tgz#0db87caf86e16a1e495277c3aad4de405ef32464" + integrity sha512-31i2VdDegR5NsHiQxPP7pWQz4u8lkQq9T1rUFHUUtT7OLr3vOcKf0dGWIeMfZ3LzIv+aCX/P3d2bwEiydCeXuA== + dependencies: + "@floating-ui/devtools" "0.2.1" + "@floating-ui/dom" "^1.6.12" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-progress@^9.2.6": + version "9.2.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-progress/-/react-progress-9.2.6.tgz#071051151784433aaaf1fec895ef34febdeae722" + integrity sha512-I3zTci64PskUGMS/2tnR3nw5hKsBKu5S7PEiCySUoy+fGSFLKGWaUC0G68EdmFCIwa4AIHG66dUyyTfr/Hjfzg== + dependencies: + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-provider@^9.20.6": + version "9.20.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-provider/-/react-provider-9.20.6.tgz#097dd52792675f0da6aa97c329e46558338539e7" + integrity sha512-yxMWLP1SZMKVLSuE4Z4617DpbzcvItjOvQl/MOiaQHdC6zfq6X+1Ud4thH49o42KIUoIeWsCBSsEyaDAdYBUvg== + dependencies: + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/core" "^1.16.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-radio@^9.3.6": + version "9.3.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-radio/-/react-radio-9.3.6.tgz#d010ec79bcdcefefbbffea4afe8db60c6768ae12" + integrity sha512-cOZzd8lN1NCVwKnkepTi9B58mEJdds2wJH8veqLv9cbNceD4Bju53xTr2UG9nIXugwdV85tptYU/o0a4oakIRA== + dependencies: + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-label" "^9.1.87" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-rating@^9.1.6": + version "9.1.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-rating/-/react-rating-9.1.6.tgz#0bba3051a98ce1aae2c3c6bb8902d9ada29baddb" + integrity sha512-uFyp+/iY9Y4ORdtljYBRDfDBZL/wdCmEHwFyNFXKSdFPePeZhkCaKZq7RH+6KCGHY4KTFqDer4IaBgxBaC2oHg== + dependencies: + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-search@^9.1.6": + version "9.1.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-search/-/react-search-9.1.6.tgz#6870c4914050148e749302cb50dc96700c25658d" + integrity sha512-3iu+axBpXuSg2wywOVj9mCqwWEiAtIseLQVFTvY8/q93/fXkHWwXEV1pgfTzPlXNWy19CLV+cuXF0v4D2+JmDA== + dependencies: + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-input" "^9.5.6" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-select@^9.2.6": + version "9.2.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-select/-/react-select-9.2.6.tgz#99f0d70a7e11a4ab5f54aeaa3ea59efe78833167" + integrity sha512-Yeb/EGOhNrCAseTj6eBgJ0QtWiyibloXepYbyZ3QryXhPeZBLR32yhKVvzGB+ScB4hdY45k/Tam8BdfofstAqw== + dependencies: + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-shared-contexts@^9.23.1": + version "9.23.1" + resolved "https://registry.yarnpkg.com/@fluentui/react-shared-contexts/-/react-shared-contexts-9.23.1.tgz#96155b604574c2207d1100727d477f5ab6e6e36d" + integrity sha512-mP+7talxLz7n0G36o7Asdvst+JPzUbqbnoMKUWRVB5YwzlOXumEgaQDgL1BkRUJYaDGOjIiSTUjHOEkBt7iSdg== + dependencies: + "@fluentui/react-theme" "^9.1.24" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-skeleton@^9.2.6": + version "9.2.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-skeleton/-/react-skeleton-9.2.6.tgz#db88971c7ef5af80283644341a8b764c81b88565" + integrity sha512-qAb0Td07EqCmyJAK53TYDfWs3NWedqAC7YRt2RVfhaQobI60+etMkXhGDwGDZwryQIFMYlNm6mSV4M5qkC4gCA== + dependencies: + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-slider@^9.3.7": + version "9.3.7" + resolved "https://registry.yarnpkg.com/@fluentui/react-slider/-/react-slider-9.3.7.tgz#6eb5886c4813076458f7facc989337660e5e4a92" + integrity sha512-PY4Z9KujrxyRZaLgdY47BlGj3LCmIiCRJE/96DSDz7iPbwfVluH0HJbBsw+MfW70c0CwyPD5VSHtPIi0pnGnKw== + dependencies: + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-spinbutton@^9.3.6": + version "9.3.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-spinbutton/-/react-spinbutton-9.3.6.tgz#44bd36013ce7c8854bb9cd80f8ed65713ec22a00" + integrity sha512-XVK1AOjKS47MBEKDDKzgePc3DfIr2f1LI+OgmbcAlhBUgyy2FGeixqdAvbJTnRehO6kRRzFjSmMLnb6c6m/W/w== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-spinner@^9.5.11": + version "9.5.11" + resolved "https://registry.yarnpkg.com/@fluentui/react-spinner/-/react-spinner-9.5.11.tgz#7d5f48c9aab6104e316d88e8cc50e4cf5f9750ac" + integrity sha512-q0mJLG7LfWSRqa2fO+Qvxw/noZWjk3HM4wurbddTOClezTcBlMXlYlad7rueu9TpzM5caGsWcMF791/gNYLHmQ== + dependencies: + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-label" "^9.1.87" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-swatch-picker@^9.2.6": + version "9.2.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-swatch-picker/-/react-swatch-picker-9.2.6.tgz#9195cd32e4799ec238d8617a4b954640adb2c7f6" + integrity sha512-s9rGkiONRxc8lmc19vbKgrkGtFzKCRv1+Cov5esIG/uJnvmTctzOLjgFj+NeWehvQgrtv8t7Bs7AszlQzfEP5A== + dependencies: + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-switch@^9.2.6": + version "9.2.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-switch/-/react-switch-9.2.6.tgz#a60bc731dcfba40037ce81b97bf3ac169af6f6b5" + integrity sha512-stFoqh/ahYmY3LPVIi3voGMPm/wcMMEepkWL8ZLYU5ZKP/knJ2Yy5peW1uVo+5d6PbLUvan9tsSB53IN/2utpA== + dependencies: + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-label" "^9.1.87" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-table@^9.16.6": + version "9.16.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-table/-/react-table-9.16.6.tgz#4873c3ccc9e7b7e797cfded69ba649cbb3cf02ba" + integrity sha512-u/skqMkdw16Lnje4CevcU1xoSspwTWRLoHXvIiWQyjSkd/mHkspflNJy/wK2aoEO5F7pPak0u72IBxMg+0KIvQ== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-avatar" "^9.7.6" + "@fluentui/react-checkbox" "^9.3.6" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-radio" "^9.3.6" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-tabs@^9.7.6": + version "9.7.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-tabs/-/react-tabs-9.7.6.tgz#bca22a799fc0436cc660c0fc32b07951618e1614" + integrity sha512-N8wey1p/bGnHNZd8L/AVU7GOiI3bodbAlL9x9L8grncPMX/WWnwTGMui7A3Ge3u2IQ3rR8XEXz/dVxFpTdv+dg== + dependencies: + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-tabster@^9.21.0", "@fluentui/react-tabster@^9.21.5", "@fluentui/react-tabster@^9.24.6": + version "9.24.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-tabster/-/react-tabster-9.24.6.tgz#b053ee6aee8e7c178704910eb3927bdf1578c54c" + integrity sha512-d0i4Yey8UE+zf+dM/wYtblRwRhxuE9uWdwsxWD5tdvDY3KZxIa9NsNW7xBRA1Az5dhvWw83fJJBd88DosX2sYw== + dependencies: + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + keyborg "^2.6.0" + tabster "^8.5.0" + +"@fluentui/react-tag-picker@^9.5.6": + version "9.5.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-tag-picker/-/react-tag-picker-9.5.6.tgz#0df301cee537321564337b77611bc581385e5162" + integrity sha512-DO65MbrWXz7YFc44TSCLGaowtnnje6UMqczCYrQVwzmQlxf00RqgbB3CVjKvW0Z3r89aNLtX9b+mYOQL4ForVg== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-combobox" "^9.14.6" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-portal" "^9.5.6" + "@fluentui/react-positioning" "^9.16.7" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-tags" "^9.5.4" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-tags@^9.5.4": + version "9.5.4" + resolved "https://registry.yarnpkg.com/@fluentui/react-tags/-/react-tags-9.5.4.tgz#3a9b9c5a650977c6037f50c59b25b0902e69e196" + integrity sha512-xmrhhmNa/hwW4p6gTjsFbctcohsiBJS96SfA/cQQ/pRpNKpjwiAZvppF3R4dBYo1Apnt9VCdAmEYhu7qmjq69A== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-avatar" "^9.7.6" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-teaching-popover@^9.4.5": + version "9.4.5" + resolved "https://registry.yarnpkg.com/@fluentui/react-teaching-popover/-/react-teaching-popover-9.4.5.tgz#a191357d14307a52dca59bb9ab97bc1fb5362ebb" + integrity sha512-axKj4EQuoDsGSK0sEdOAEuwg3ew7Maxu4xKF2Z2jOOf0J7+6lKiZilTzt3gf5XLHUzFMU2bTM7VVAN8O8Et04A== + dependencies: + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-button" "^9.4.6" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-popover" "^9.10.6" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + use-sync-external-store "^1.2.0" + +"@fluentui/react-text@^9.4.36": + version "9.4.36" + resolved "https://registry.yarnpkg.com/@fluentui/react-text/-/react-text-9.4.36.tgz#d4d6e12ef9059fd087ffc76457fe0e174e138ac1" + integrity sha512-oLSGz6uksooCQrc+FXvWwAZCP+ucn2h12vZFyWSAOVODDtQMjtycol03p408BEHnPBQbrYaQCFpd3Id5eLuxBg== + dependencies: + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-textarea@^9.4.6": + version "9.4.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-textarea/-/react-textarea-9.4.6.tgz#6e6c3dea377bbc70f088269a647fed5241e25da5" + integrity sha512-zdpeCSnVJihbPXHeAYHa1MiO7dJba3Ugtyu7TqJkmiy0Lr5OfeTkX2nLchOPKiEDjQFfSviqDNYZERwO2NGD1g== + dependencies: + "@fluentui/react-field" "^9.2.6" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-theme@^9.1.19", "@fluentui/react-theme@^9.1.24": + version "9.1.24" + resolved "https://registry.yarnpkg.com/@fluentui/react-theme/-/react-theme-9.1.24.tgz#8ad614df32a60278719a073ea7e308f5016aae34" + integrity sha512-OhVKYD7CMYHxzJEn4PtIszledj8hbQJNWBMfIZsp4Sytdp9vCi0txIQUx4BhS1WqtQPhNGCF16eW9Q3NRrnIrQ== + dependencies: + "@fluentui/tokens" "1.0.0-alpha.21" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-toast@^9.4.8": + version "9.4.8" + resolved "https://registry.yarnpkg.com/@fluentui/react-toast/-/react-toast-9.4.8.tgz#bfffcb011fcbfea1eb2942420958add9cfe47505" + integrity sha512-1welldVf/M/c7msCwB8a0yFgKjIF/aUxAgjTHza9jEmxBl45oCzPZY7PVApCY2sSx+iRn8XjSKRkYSPgHUYzKA== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-motion" "^9.7.2" + "@fluentui/react-motion-components-preview" "^0.4.9" + "@fluentui/react-portal" "^9.5.6" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-toolbar@^9.4.5": + version "9.4.5" + resolved "https://registry.yarnpkg.com/@fluentui/react-toolbar/-/react-toolbar-9.4.5.tgz#26e8b8a1d55163dc62f43e8bd234240644434733" + integrity sha512-/Za5QHVqcF1bLW7FIRebl17TI+MCdoVqvHoaE7xodRmAA0a5MWcs3aqtumaeQjZBnGh9HsFYmxTKdh0KEu4LVg== + dependencies: + "@fluentui/react-button" "^9.4.6" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-divider" "^9.2.86" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-radio" "^9.3.6" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-tooltip@^9.6.6": + version "9.6.6" + resolved "https://registry.yarnpkg.com/@fluentui/react-tooltip/-/react-tooltip-9.6.6.tgz#386346b9f5f837552cc57c93f4f296b1b7aa6fd9" + integrity sha512-4EHxH5CvzPQjOjl9opldAhSAVSOoUo4ei412RoCRASzoaVBJwQ81r2MaVlf9P84G6WOUUXttRbUQ+0jWV5WoKg== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-portal" "^9.5.6" + "@fluentui/react-positioning" "^9.16.7" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-tree@^9.10.9": + version "9.10.9" + resolved "https://registry.yarnpkg.com/@fluentui/react-tree/-/react-tree-9.10.9.tgz#ba8af52517cc875ae3c2f8b8e1e8aa2f1e0541c3" + integrity sha512-Pj/eSXVVw3kGae7Jl3ZBaRqjSOm9JytzgA13eYdHpx58YpqGsYOU6G5CFwx28pTQKeIZIfsIgTDPhD+S5LcVOQ== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-aria" "^9.14.6" + "@fluentui/react-avatar" "^9.7.6" + "@fluentui/react-button" "^9.4.6" + "@fluentui/react-checkbox" "^9.3.6" + "@fluentui/react-context-selector" "^9.1.76" + "@fluentui/react-icons" "^2.0.245" + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-motion" "^9.7.2" + "@fluentui/react-motion-components-preview" "^0.4.9" + "@fluentui/react-radio" "^9.3.6" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-tabster" "^9.24.6" + "@fluentui/react-theme" "^9.1.24" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-utilities@^9.18.10", "@fluentui/react-utilities@^9.18.7", "@fluentui/react-utilities@^9.19.0": + version "9.19.0" + resolved "https://registry.yarnpkg.com/@fluentui/react-utilities/-/react-utilities-9.19.0.tgz#e85cd29e5462f745140a286a380ff961aef4459f" + integrity sha512-66Kdpr4xZsov6KSqbPDmKR5CB96RUPZuWihMC3RYHj9uH+oxd81k2Jyrb6rM058xjVKDFSFVLUZlsp1Mgts38w== + dependencies: + "@fluentui/keyboard-keys" "^9.0.8" + "@fluentui/react-shared-contexts" "^9.23.1" + "@swc/helpers" "^0.5.1" + +"@fluentui/react-virtualizer@9.0.0-alpha.96": + version "9.0.0-alpha.96" + resolved "https://registry.yarnpkg.com/@fluentui/react-virtualizer/-/react-virtualizer-9.0.0-alpha.96.tgz#7a60bbacff894626ad576eb807e7d40e9fa417c5" + integrity sha512-0o9RSTAAIoJ4xdM2g8hF5u98Up0OHRknRhMolZHZDoqXEvhJ5GroGtp+NPfU7LxU+dxHrZLx9gQ6wVWe/35ZzQ== + dependencies: + "@fluentui/react-jsx-runtime" "^9.0.54" + "@fluentui/react-shared-contexts" "^9.23.1" + "@fluentui/react-utilities" "^9.19.0" + "@griffel/react" "^1.5.22" + "@swc/helpers" "^0.5.1" + +"@fluentui/tokens@1.0.0-alpha.21": + version "1.0.0-alpha.21" + resolved "https://registry.yarnpkg.com/@fluentui/tokens/-/tokens-1.0.0-alpha.21.tgz#25738cabb95aa5a90dad92397325ce70044ad5f7" + integrity sha512-xQ1T56sNgDFGl+kJdIwhz67mHng8vcwO7Dvx5Uja4t+NRULQBgMcJ4reUo4FGF3TjufHj08pP0/OnKQgnOaSVg== + dependencies: + "@swc/helpers" "^0.5.1" + +"@griffel/core@^1.16.0", "@griffel/core@^1.19.2": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@griffel/core/-/core-1.19.2.tgz#994070585bb49795d882355fc0787eb9878db71c" + integrity sha512-WkB/QQkjy9dE4vrNYGhQvRRUHFkYVOuaznVOMNTDT4pS9aTJ9XPrMTXXlkpcwaf0D3vNKoerj4zAwnU2lBzbOg== + dependencies: + "@emotion/hash" "^0.9.0" + "@griffel/style-types" "^1.3.0" + csstype "^3.1.3" + rtl-css-js "^1.16.1" + stylis "^4.2.0" + tslib "^2.1.0" + +"@griffel/react@^1.0.0", "@griffel/react@^1.5.14", "@griffel/react@^1.5.22": + version "1.5.30" + resolved "https://registry.yarnpkg.com/@griffel/react/-/react-1.5.30.tgz#6638e79d88573e5a71651a909326428cac2ce9c3" + integrity sha512-1q4ojbEVFY5YA0j1NamP0WWF4BKh+GHsVugltDYeEgEaVbH3odJ7tJabuhQgY+7Nhka0pyEFWSiHJev0K3FSew== + dependencies: + "@griffel/core" "^1.19.2" + tslib "^2.1.0" + +"@griffel/style-types@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@griffel/style-types/-/style-types-1.3.0.tgz#42b4f1902a0221a9a8334fda12a2fe88f13d65ee" + integrity sha512-bHwD3sUE84Xwv4dH011gOKe1jul77M1S6ZFN9Tnq8pvZ48UMdY//vtES6fv7GRS5wXYT4iqxQPBluAiYAfkpmw== + dependencies: + csstype "^3.1.3" + +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.6" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" + integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.3.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/momoa@^3.3.4": + version "3.3.8" + resolved "https://registry.yarnpkg.com/@humanwhocodes/momoa/-/momoa-3.3.8.tgz#b00630bf689b6f758419c029e15a4be25c12179b" + integrity sha512-/3PZzor2imi/RLLcnHztkwA79txiVvW145Ve2cp5dxRcH5qOUNJPToasqLFHniTfw4B4lT7jGDdBOPXbXYlIMQ== + +"@humanwhocodes/retry@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" + integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== + +"@humanwhocodes/retry@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.2.tgz#1860473de7dfa1546767448f333db80cb0ff2161" + integrity sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ== + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.8" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" + integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@lukeed/csprng@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@lukeed/csprng/-/csprng-1.1.0.tgz#1e3e4bd05c1cc7a0b2ddbd8a03f39f6e4b5e6cfe" + integrity sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA== + +"@modelcontextprotocol/sdk@^1.8.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.11.0.tgz#9f1762efe6f3365f0bf3b019cc9bd1629d19bc50" + integrity sha512-k/1pb70eD638anoi0e8wUGAlbMJXyvdV4p62Ko+EZ7eBe1xMx8Uhak1R5DgfoofsK5IBBnRwsYGTaLZl+6/+RQ== + dependencies: + content-type "^1.0.5" + cors "^2.8.5" + cross-spawn "^7.0.3" + eventsource "^3.0.2" + express "^5.0.1" + express-rate-limit "^7.5.0" + pkce-challenge "^5.0.0" + raw-body "^3.0.0" + zod "^3.23.8" + zod-to-json-schema "^3.24.1" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@pnpm/config.env-replace@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz#ab29da53df41e8948a00f2433f085f54de8b3a4c" + integrity sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w== + +"@pnpm/network.ca-file@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz#2ab05e09c1af0cdf2fcf5035bea1484e222f7983" + integrity sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA== + dependencies: + graceful-fs "4.2.10" + +"@pnpm/npm-conf@^2.1.0": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz#bb375a571a0bd63ab0a23bece33033c683e9b6b0" + integrity sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw== + dependencies: + "@pnpm/config.env-replace" "^1.1.0" + "@pnpm/network.ca-file" "^1.0.1" + config-chain "^1.1.11" + +"@rollup/pluginutils@^5.1.4": + version "5.1.4" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.4.tgz#bb94f1f9eaaac944da237767cdfee6c5b2262d4a" + integrity sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^4.0.2" + +"@rollup/rollup-android-arm-eabi@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.1.tgz#e1562d360bca73c7bef6feef86098de3a2f1d442" + integrity sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw== + +"@rollup/rollup-android-arm64@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.1.tgz#37ba63940211673e15dcc5f469a78e34276dbca7" + integrity sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw== + +"@rollup/rollup-darwin-arm64@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.1.tgz#58b1eb86d997d71dabc5b78903233a3c27438ca0" + integrity sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA== + +"@rollup/rollup-darwin-x64@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.1.tgz#5e22dab3232b1e575d930ce891abb18fe19c58c9" + integrity sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw== + +"@rollup/rollup-freebsd-arm64@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.1.tgz#04c892d9ff864d66e31419634726ab0bebb33707" + integrity sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw== + +"@rollup/rollup-freebsd-x64@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.1.tgz#f4b1e091f7cf5afc9e3a029d70128ad56409ecfb" + integrity sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q== + +"@rollup/rollup-linux-arm-gnueabihf@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.1.tgz#c8814bb5ce047a81b1fe4a33628dfd4ac52bd864" + integrity sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg== + +"@rollup/rollup-linux-arm-musleabihf@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.1.tgz#5b4e7bd83cbebbf5ffe958802dcfd4ee34bf73a3" + integrity sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg== + +"@rollup/rollup-linux-arm64-gnu@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.1.tgz#141c848e53cee011e82a11777b8a51f1b3e8d77c" + integrity sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg== + +"@rollup/rollup-linux-arm64-musl@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.1.tgz#22ebeaf2fa301aa4aa6c84b760e6cd1d1ac7eb1e" + integrity sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ== + +"@rollup/rollup-linux-loongarch64-gnu@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.1.tgz#20b77dc78e622f5814ff8e90c14c938ceb8043bc" + integrity sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ== + +"@rollup/rollup-linux-powerpc64le-gnu@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.1.tgz#2c90f99c987ef1198d4f8d15d754c286e1f07b13" + integrity sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg== + +"@rollup/rollup-linux-riscv64-gnu@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.1.tgz#9336fd5e47d7f4760d02aa85f76976176eef53ca" + integrity sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ== + +"@rollup/rollup-linux-riscv64-musl@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.1.tgz#d75b4d54d46439bb5c6c13762788f57e798f5670" + integrity sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA== + +"@rollup/rollup-linux-s390x-gnu@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.1.tgz#e9f09b802f1291839247399028beaef9ce034c81" + integrity sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg== + +"@rollup/rollup-linux-x64-gnu@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.1.tgz#0413169dc00470667dea8575c1129d4e7a73eb29" + integrity sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ== + +"@rollup/rollup-linux-x64-musl@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.1.tgz#c76fd593323c60ea219439a00da6c6d33ffd0ea6" + integrity sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ== + +"@rollup/rollup-win32-arm64-msvc@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.1.tgz#c7724c386eed0bda5ae7143e4081c1910cab349b" + integrity sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg== + +"@rollup/rollup-win32-ia32-msvc@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.1.tgz#7749e1b65cb64fe6d41ad1ad9e970a0ccc8ac350" + integrity sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA== + +"@rollup/rollup-win32-x64-msvc@4.40.1": + version "4.40.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.1.tgz#8078b71fe0d5825dcbf83d52a7dc858b39da165c" + integrity sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA== + +"@stylistic/eslint-plugin@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin/-/eslint-plugin-4.2.0.tgz#7860ea84aa7ee3b21757907b863eb62f4f8b0455" + integrity sha512-8hXezgz7jexGHdo5WN6JBEIPHCSFyyU4vgbxevu4YLVS5vl+sxqAAGyXSzfNDyR6xMNSH5H1x67nsXcYMOHtZA== + dependencies: + "@typescript-eslint/utils" "^8.23.0" + eslint-visitor-keys "^4.2.0" + espree "^10.3.0" + estraverse "^5.3.0" + picomatch "^4.0.2" + +"@swc/helpers@^0.5.1": + version "0.5.17" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.17.tgz#5a7be95ac0f0bf186e7e6e890e7a6f6cda6ce971" + integrity sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A== + dependencies: + tslib "^2.8.0" + +"@types/babel__core@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.27.0.tgz#b5819294c51179957afaec341442f9341e4108a9" + integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.7.tgz#968cdc2366ec3da159f61166428ee40f370e56c2" + integrity sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng== + dependencies: + "@babel/types" "^7.20.7" + +"@types/chrome@^0.0.280": + version "0.0.280" + resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.280.tgz#7ef46940c1aa78947508c2371993a301df8c4115" + integrity sha512-AotSmZrL9bcZDDmSI1D9dE7PGbhOur5L0cKxXd7IqbVizQWCY4gcvupPUVsQ4FfDj3V2tt/iOpomT9EY0s+w1g== + dependencies: + "@types/filesystem" "*" + "@types/har-format" "*" + +"@types/estree@1.0.7", "@types/estree@^1.0.0", "@types/estree@^1.0.6": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" + integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== + +"@types/filesystem@*": + version "0.0.36" + resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.36.tgz#7227c2d76bfed1b21819db310816c7821d303857" + integrity sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA== + dependencies: + "@types/filewriter" "*" + +"@types/filewriter@*": + version "0.0.33" + resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.33.tgz#d9d611db9d9cd99ae4e458de420eeb64ad604ea8" + integrity sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g== + +"@types/har-format@*": + version "1.2.16" + resolved "https://registry.yarnpkg.com/@types/har-format/-/har-format-1.2.16.tgz#b71ede8681400cc08b3685f061c31e416cf94944" + integrity sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A== + +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/minimatch@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" + integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== + +"@types/node@*": + version "22.15.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.3.tgz#b7fb9396a8ec5b5dfb1345d8ac2502060e9af68b" + integrity sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw== + dependencies: + undici-types "~6.21.0" + +"@types/prop-types@*": + version "15.7.14" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.14.tgz#1433419d73b2a7ebfc6918dcefd2ec0d5cd698f2" + integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ== + +"@types/react-dom@^18.3.1": + version "18.3.7" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.7.tgz#b89ddf2cd83b4feafcc4e2ea41afdfb95a0d194f" + integrity sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ== + +"@types/react@^18.3.1": + version "18.3.20" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.20.tgz#b0dccda9d2f1bc24d2a04b1d0cb5d0b9a3576ad3" + integrity sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + +"@types/webextension-polyfill@^0.12.1": + version "0.12.3" + resolved "https://registry.yarnpkg.com/@types/webextension-polyfill/-/webextension-polyfill-0.12.3.tgz#a4ac3452b816e4bd646024007a886234e2f6293e" + integrity sha512-F58aDVSeN/MjUGazXo/cPsmR76EvqQhQ1v4x23hFjUX0cfAJYE+JBWwiOGW36/VJGGxoH74sVlRIF3z7SJCKyg== + +"@types/yauzl@^2.9.1": + version "2.10.3" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999" + integrity sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q== + dependencies: + "@types/node" "*" + +"@typescript-eslint/eslint-plugin@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.1.tgz#62f1befe59647524994e89de4516d8dcba7a850a" + integrity sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.31.1" + "@typescript-eslint/type-utils" "8.31.1" + "@typescript-eslint/utils" "8.31.1" + "@typescript-eslint/visitor-keys" "8.31.1" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^2.0.1" + +"@typescript-eslint/parser@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.31.1.tgz#e9b0ccf30d37dde724ee4d15f4dbc195995cce1b" + integrity sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q== + dependencies: + "@typescript-eslint/scope-manager" "8.31.1" + "@typescript-eslint/types" "8.31.1" + "@typescript-eslint/typescript-estree" "8.31.1" + "@typescript-eslint/visitor-keys" "8.31.1" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz#1eb52e76878f545e4add142e0d8e3e97e7aa443b" + integrity sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw== + dependencies: + "@typescript-eslint/types" "8.31.1" + "@typescript-eslint/visitor-keys" "8.31.1" + +"@typescript-eslint/type-utils@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.31.1.tgz#be0f438fb24b03568e282a0aed85f776409f970c" + integrity sha512-fNaT/m9n0+dpSp8G/iOQ05GoHYXbxw81x+yvr7TArTuZuCA6VVKbqWYVZrV5dVagpDTtj/O8k5HBEE/p/HM5LA== + dependencies: + "@typescript-eslint/typescript-estree" "8.31.1" + "@typescript-eslint/utils" "8.31.1" + debug "^4.3.4" + ts-api-utils "^2.0.1" + +"@typescript-eslint/types@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.31.1.tgz#478ed6f7e8aee1be7b63a60212b6bffe1423b5d4" + integrity sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ== + +"@typescript-eslint/typescript-estree@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz#37792fe7ef4d3021c7580067c8f1ae66daabacdf" + integrity sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag== + dependencies: + "@typescript-eslint/types" "8.31.1" + "@typescript-eslint/visitor-keys" "8.31.1" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^2.0.1" + +"@typescript-eslint/utils@8.31.1", "@typescript-eslint/utils@^8.23.0": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.31.1.tgz#5628ea0393598a0b2f143d0fc6d019f0dee9dd14" + integrity sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.31.1" + "@typescript-eslint/types" "8.31.1" + "@typescript-eslint/typescript-estree" "8.31.1" + +"@typescript-eslint/visitor-keys@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz#6742b0e3ba1e0c1e35bdaf78c03e759eb8dd8e75" + integrity sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw== + dependencies: + "@typescript-eslint/types" "8.31.1" + eslint-visitor-keys "^4.2.0" + +"@vitejs/plugin-react@^4.3.4": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz#d7d1e9c9616d7536b0953637edfee7c6cbe2fe0f" + integrity sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w== + dependencies: + "@babel/core" "^7.26.10" + "@babel/plugin-transform-react-jsx-self" "^7.25.9" + "@babel/plugin-transform-react-jsx-source" "^7.25.9" + "@types/babel__core" "^7.20.5" + react-refresh "^0.17.0" + +"@webext-core/fake-browser@^1.3.1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@webext-core/fake-browser/-/fake-browser-1.3.2.tgz#e41443fd857e1c49586c6ce881eaf09de4e101fe" + integrity sha512-jFyPWWz+VkHAC9DRIiIPOyu6X/KlC8dYqSKweHz6tsDb86QawtVgZSpYcM+GOQBlZc5DHFo92jJ7cIq4uBnU0A== + dependencies: + lodash.merge "^4.6.2" + +"@webext-core/isolated-element@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@webext-core/isolated-element/-/isolated-element-1.1.2.tgz#b50f2698ae93e2c4ab621048c1d569d7a9d3908f" + integrity sha512-CNHYhsIR8TPkPb+4yqTIuzaGnVn/Fshev5fyoPW+/8Cyc93tJbCjP9PC1XSK6fDWu+xASdPHLZaoa2nWAYoxeQ== + dependencies: + is-potential-custom-element-name "^1.0.1" + +"@webext-core/match-patterns@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@webext-core/match-patterns/-/match-patterns-1.0.3.tgz#d590e5063e21a6a83d245700dfeb5489fbd99a77" + integrity sha512-NY39ACqCxdKBmHgw361M9pfJma8e4AZo20w9AY+5ZjIj1W2dvXC8J31G5fjfOGbulW9w4WKpT8fPooi0mLkn9A== + +"@webext-core/messaging@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@webext-core/messaging/-/messaging-2.2.0.tgz#d941a5b5cfe179af0fe365d2d9b4ce6d88ed3c5c" + integrity sha512-CRKFSH8ZAp55QpzfseOO/RlW6fAVSGWYNJK1j23khB855Ba9wHu8PB3uuqMVZtfEAwAmsw/2U8HIkony5adFBQ== + dependencies: + uid "^2.0.2" + serialize-error "^11.0.0" + webextension-polyfill "^0.10.0" + +"@wxt-dev/i18n@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@wxt-dev/i18n/-/i18n-0.2.3.tgz#5688cbdf5324e86fbd65d585073121bf8d493085" + integrity sha512-2X005PB1r+6sDYMOuZD5hxSOPkogEZZTLB5HEsOotQ5RYXF3c/OOMD+DffVeq+S0yKY2Dmg4Ujfu0Pq4busJYQ== + dependencies: + chokidar "^3.6.0" + confbox "^0.1.7" + fast-glob "^3.3.2" + +"@wxt-dev/module-react@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@wxt-dev/module-react/-/module-react-1.1.3.tgz#b103d90f228b9bbc6dddb47d6316e7b4c5165141" + integrity sha512-ede2FLS3sdJwtyI61jvY1UiF194ouv3wxm+fCYjfP4FfvoXQbif8UuusYBC0KSa/L2AL9Cfa/lEvsdNYrKFUaA== + dependencies: + "@vitejs/plugin-react" "^4.3.4" + +"@wxt-dev/storage@^1.0.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@wxt-dev/storage/-/storage-1.1.1.tgz#06b4b785bcfc7113733fda189ab1c2cd7a5e1825" + integrity sha512-H1vYWeoWz03INV4r+sLYDFil88b3rgMMfgGp/EXy3bLbveJeiMiFs/G0bsBN2Ra87Iqlf2oVYRb/ABQpAugbew== + dependencies: + async-mutex "^0.5.0" + dequal "^2.0.3" + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +accepts@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-2.0.0.tgz#bbcf4ba5075467f3f2131eab3cffc73c2f5d7895" + integrity sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng== + dependencies: + mime-types "^3.0.0" + negotiator "^1.0.0" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.14.0: + version "8.14.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" + integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== + +adm-zip@~0.5.x: + version "0.5.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.16.tgz#0b5e4c779f07dedea5805cdccb1147071d94a909" + integrity sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ== + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + 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" + +ansi-align@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + +ansi-escapes@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.0.0.tgz#00fc19f491bbb18e1d481b97868204f92109bfe7" + integrity sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw== + dependencies: + environment "^1.0.0" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.0.0, ansi-styles@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b" + integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw== + dependencies: + call-bound "^1.0.3" + is-array-buffer "^3.0.5" + +array-differ@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-4.0.0.tgz#aa3c891c653523290c880022f45b06a42051b026" + integrity sha512-Q6VPTLMsmXZ47ENG3V+wQyZS1ZxXMxFyYzA+Z/GMrJ6yIutAIEf9wTyroTzmGjNfox9/h3GdGBCVh43GVFx4Uw== + +array-includes@^3.1.6, array-includes@^3.1.8: + version "3.1.8" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" + integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" + is-string "^1.0.7" + +array-union@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" + integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== + +array.prototype.findlast@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" + integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" + +array.prototype.flat@^1.3.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz#534aaf9e6e8dd79fb6b9a9917f839ef1ec63afe5" + integrity sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" + +array.prototype.flatmap@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz#712cc792ae70370ae40586264629e33aab5dd38b" + integrity sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" + +array.prototype.tosorted@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" + integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" + +arraybuffer.prototype.slice@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c" + integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + is-array-buffer "^3.0.4" + +async-function@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" + integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== + +async-mutex@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.5.0.tgz#353c69a0b9e75250971a64ac203b0ebfddd75482" + integrity sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA== + dependencies: + tslib "^2.4.0" + +async@^3.2.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" + integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== + +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + +atomically@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/atomically/-/atomically-2.0.3.tgz#27e47bbe39994d324918491ba7c0edb7783e56cb" + integrity sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw== + dependencies: + stubborn-fs "^1.2.5" + when-exit "^2.1.1" + +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +big-integer@^1.6.44: + version "1.6.52" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" + integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +bl@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273" + integrity sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ== + dependencies: + buffer "^6.0.3" + inherits "^2.0.4" + readable-stream "^3.4.0" + +bluebird@~3.7: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +body-parser@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.2.0.tgz#f7a9656de305249a715b549b7b8fd1ab9dfddcfa" + integrity sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg== + dependencies: + bytes "^3.1.2" + content-type "^1.0.5" + debug "^4.4.0" + http-errors "^2.0.0" + iconv-lite "^0.6.3" + on-finished "^2.4.1" + qs "^6.14.0" + raw-body "^3.0.0" + type-is "^2.0.0" + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +boxen@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-8.0.1.tgz#7e9fcbb45e11a2d7e6daa8fdcebfc3242fc19fe3" + integrity sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw== + dependencies: + ansi-align "^3.0.1" + camelcase "^8.0.0" + chalk "^5.3.0" + cli-boxes "^3.0.0" + string-width "^7.2.0" + type-fest "^4.21.0" + widest-line "^5.0.0" + wrap-ansi "^9.0.0" + +bplist-parser@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" + integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw== + dependencies: + big-integer "^1.6.44" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browserslist@^4.24.0: + version "4.24.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.5.tgz#aa0f5b8560fe81fde84c6dcb38f759bafba0e11b" + integrity sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw== + dependencies: + caniuse-lite "^1.0.30001716" + electron-to-chromium "^1.5.149" + node-releases "^2.0.19" + update-browserslist-db "^1.1.3" + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +bundle-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a" + integrity sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw== + dependencies: + run-applescript "^5.0.0" + +bundle-name@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-4.1.0.tgz#f3b96b34160d6431a19d7688135af7cfb8797889" + integrity sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q== + dependencies: + run-applescript "^7.0.0" + +bytes@3.1.2, bytes@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +c12@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/c12/-/c12-3.0.3.tgz#4d6d4d35f084606ff616d1bcae60e6676eacd4bd" + integrity sha512-uC3MacKBb0Z15o5QWCHvHWj5Zv34pGQj9P+iXKSpTuSGFS0KKhUWf4t9AJ+gWjYOdmWCPEGpEzm8sS0iqbpo1w== + dependencies: + chokidar "^4.0.3" + confbox "^0.2.2" + defu "^6.1.4" + dotenv "^16.4.7" + exsolve "^1.0.4" + giget "^2.0.0" + jiti "^2.4.2" + ohash "^2.0.11" + pathe "^2.0.3" + perfect-debounce "^1.0.0" + pkg-types "^2.1.0" + rc9 "^2.1.2" + +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-8.0.0.tgz#c0d36d418753fb6ad9c5e0437579745c1c14a534" + integrity sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA== + +caniuse-lite@^1.0.30001716: + version "1.0.30001716" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001716.tgz#39220dfbc58c85d9d4519e7090b656aa11ca4b85" + integrity sha512-49/c1+x3Kwz7ZIWt+4DvK3aMJy9oYXXG6/97JKsnjdCk/6n9vVyWL8NAwVt95Lwt9eigI10Hl782kDfZUUlRXw== + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^5.0.0, chalk@^5.3.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.4.1.tgz#1b48bf0963ec158dce2aacf69c093ae2dd2092d8" + integrity sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w== + +chokidar@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + 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" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +chrome-launcher@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-1.1.2.tgz#52eff6b3fd7f24b65192b2624a108dadbcca4b9d" + integrity sha512-YclTJey34KUm5jB1aEJCq807bSievi7Nb/TU4Gu504fUYi3jw3KCIaH6L7nFWQhdEgH3V+wCh+kKD1P5cXnfxw== + dependencies: + "@types/node" "*" + escape-string-regexp "^4.0.0" + is-wsl "^2.2.0" + lighthouse-logger "^2.0.1" + +ci-info@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.2.0.tgz#cbd21386152ebfe1d56f280a3b5feccbd96764c7" + integrity sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg== + +citty@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/citty/-/citty-0.1.6.tgz#0f7904da1ed4625e1a9ea7e0fa780981aab7c5e4" + integrity sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ== + dependencies: + consola "^3.2.3" + +cli-boxes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145" + integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== + +cli-cursor@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" + integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg== + dependencies: + restore-cursor "^4.0.0" + +cli-cursor@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-5.0.0.tgz#24a4831ecf5a6b01ddeb32fb71a4b2088b0dce38" + integrity sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw== + dependencies: + restore-cursor "^5.0.0" + +cli-highlight@^2.1.11: + version "2.1.11" + resolved "https://registry.yarnpkg.com/cli-highlight/-/cli-highlight-2.1.11.tgz#49736fa452f0aaf4fae580e30acb26828d2dc1bf" + integrity sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg== + dependencies: + chalk "^4.0.0" + highlight.js "^10.7.1" + mz "^2.4.0" + parse5 "^5.1.1" + parse5-htmlparser2-tree-adapter "^6.0.0" + yargs "^16.0.0" + +cli-spinners@^2.6.1, cli-spinners@^2.9.2: + version "2.9.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + +cli-truncate@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-4.0.0.tgz#6cc28a2924fee9e25ce91e973db56c7066e6172a" + integrity sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA== + dependencies: + slice-ansi "^5.0.0" + string-width "^7.0.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.20: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + integrity sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A== + dependencies: + graceful-readlink ">= 1.0.0" + +commander@^9.1.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-stream@^1.4.7: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +confbox@^0.1.7, confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + +confbox@^0.2.1, confbox@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.2.2.tgz#8652f53961c74d9e081784beed78555974a9c110" + integrity sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ== + +config-chain@^1.1.11: + version "1.1.13" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4" + integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +configstore@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-7.0.0.tgz#4461561fc51cb40e5ee1161230bc0337e069cc6b" + integrity sha512-yk7/5PN5im4qwz0WFZW3PXnzHgPu9mX29Y8uZ3aefe2lBPC1FYttWZRcaW9fKkT0pBCJyuQ2HfbmPVaODi9jcQ== + dependencies: + atomically "^2.0.3" + dot-prop "^9.0.0" + graceful-fs "^4.2.11" + xdg-basedir "^5.1.0" + +consola@^3.2.3, consola@^3.4.0: + version "3.4.2" + resolved "https://registry.yarnpkg.com/consola/-/consola-3.4.2.tgz#5af110145397bb67afdab77013fdc34cae590ea7" + integrity sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA== + +content-disposition@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-1.0.0.tgz#844426cb398f934caefcbb172200126bc7ceace2" + integrity sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg== + dependencies: + safe-buffer "5.2.1" + +content-type@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +cookie-signature@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.2.tgz#57c7fc3cc293acab9fec54d73e15690ebe4a1793" + integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg== + +cookie@^0.7.1: + version "0.7.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" + integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@^2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + +css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +cssom@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" + integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== + +csstype@^3.0.2, csstype@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + +data-view-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570" + integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-data-view "^1.0.2" + +data-view-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz#9e80f7ca52453ce3e93d25a35318767ea7704735" + integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-data-view "^1.0.2" + +data-view-byte-offset@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz#068307f9b71ab76dbbe10291389e020856606191" + integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +debounce@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" + integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== + +debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + +debug@~4.3.1: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +default-browser-id@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c" + integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA== + dependencies: + bplist-parser "^0.2.0" + untildify "^4.0.0" + +default-browser-id@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-5.0.0.tgz#a1d98bf960c15082d8a3fa69e83150ccccc3af26" + integrity sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA== + +default-browser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-4.0.0.tgz#53c9894f8810bf86696de117a6ce9085a3cbc7da" + integrity sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA== + dependencies: + bundle-name "^3.0.0" + default-browser-id "^3.0.0" + execa "^7.1.1" + titleize "^3.0.0" + +default-browser@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-5.2.1.tgz#7b7ba61204ff3e425b556869ae6d3e9d9f1712cf" + integrity sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg== + dependencies: + bundle-name "^4.1.0" + default-browser-id "^5.0.0" + +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + +define-properties@^1.1.3, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +defu@^6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" + integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg== + +depd@2.0.0, depd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +dequal@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + +destr@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.5.tgz#7d112ff1b925fb8d2079fac5bdb4a90973b51fdb" + integrity sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA== + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +dom-helpers@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + +domutils@^3.0.1, domutils@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78" + integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + +dot-prop@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-9.0.0.tgz#bae5982fe6dc6b8fddb92efef4f2ddff26779e92" + integrity sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ== + dependencies: + type-fest "^4.18.2" + +dotenv-expand@^12.0.1: + version "12.0.2" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-12.0.2.tgz#0c812c61a71901b8bd90387e0e0edd0678b8a181" + integrity sha512-lXpXz2ZE1cea1gL4sz2Ipj8y4PiVjytYr3Ij0SWoms1PGxIv7m2CRKuRuCRtHdVuvM/hNJPMxt5PbhboNC4dPQ== + dependencies: + dotenv "^16.4.5" + +dotenv@^16.3.1, dotenv@^16.4.5, dotenv@^16.4.7: + version "16.5.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.5.0.tgz#092b49f25f808f020050051d1ff258e404c78692" + integrity sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg== + +dunder-proto@^1.0.0, dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.5.149: + version "1.5.149" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.149.tgz#b6d1a468b9537165e2494d0b5b82e9b3392d0ddb" + integrity sha512-UyiO82eb9dVOx8YO3ajDf9jz2kKyt98DEITRdeLPstOEuTlLzDA4Gyq5K9he71TQziU5jUVu2OAu5N48HmQiyQ== + +embla-carousel-autoplay@^8.5.1: + version "8.6.0" + resolved "https://registry.yarnpkg.com/embla-carousel-autoplay/-/embla-carousel-autoplay-8.6.0.tgz#bc86c97de00d52ec34b05058736ef50af6e0d0e4" + integrity sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA== + +embla-carousel-fade@^8.5.1: + version "8.6.0" + resolved "https://registry.yarnpkg.com/embla-carousel-fade/-/embla-carousel-fade-8.6.0.tgz#92d19ecd54441eb6f37910bf9e16fd3f547e3374" + integrity sha512-qaYsx5mwCz72ZrjlsXgs1nKejSrW+UhkbOMwLgfRT7w2LtdEB03nPRI06GHuHv5ac2USvbEiX2/nAHctcDwvpg== + +embla-carousel@^8.5.1: + version "8.6.0" + resolved "https://registry.yarnpkg.com/embla-carousel/-/embla-carousel-8.6.0.tgz#abcedff2bff36992ea8ac27cd30080ca5b6a3f58" + integrity sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA== + +emoji-regex@^10.3.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.4.0.tgz#03553afea80b3975749cfcb36f776ca268e413d4" + integrity sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +entities@^4.2.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + +entities@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.0.tgz#09c9e29cb79b0a6459a9b9db9efb418ac5bb8e51" + integrity sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw== + +environment@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" + integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== + +error-ex@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.17.5, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5, es-abstract@^1.23.6, es-abstract@^1.23.9: + version "1.23.9" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.9.tgz#5b45994b7de78dada5c1bebf1379646b32b9d606" + integrity sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA== + dependencies: + array-buffer-byte-length "^1.0.2" + arraybuffer.prototype.slice "^1.0.4" + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" + data-view-buffer "^1.0.2" + data-view-byte-length "^1.0.2" + data-view-byte-offset "^1.0.1" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-set-tostringtag "^2.1.0" + es-to-primitive "^1.3.0" + function.prototype.name "^1.1.8" + get-intrinsic "^1.2.7" + get-proto "^1.0.0" + get-symbol-description "^1.1.0" + globalthis "^1.0.4" + gopd "^1.2.0" + has-property-descriptors "^1.0.2" + has-proto "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + internal-slot "^1.1.0" + is-array-buffer "^3.0.5" + is-callable "^1.2.7" + is-data-view "^1.0.2" + is-regex "^1.2.1" + is-shared-array-buffer "^1.0.4" + is-string "^1.1.1" + is-typed-array "^1.1.15" + is-weakref "^1.1.0" + math-intrinsics "^1.1.0" + object-inspect "^1.13.3" + object-keys "^1.1.1" + object.assign "^4.1.7" + own-keys "^1.0.1" + regexp.prototype.flags "^1.5.3" + safe-array-concat "^1.1.3" + safe-push-apply "^1.0.0" + safe-regex-test "^1.1.0" + set-proto "^1.0.0" + string.prototype.trim "^1.2.10" + string.prototype.trimend "^1.0.9" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.3" + typed-array-byte-length "^1.0.3" + typed-array-byte-offset "^1.0.4" + typed-array-length "^1.0.7" + unbox-primitive "^1.1.0" + which-typed-array "^1.1.18" + +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-iterator-helpers@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz#d1dd0f58129054c0ad922e6a9a1e65eef435fe75" + integrity sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-abstract "^1.23.6" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.3" + function-bind "^1.1.2" + get-intrinsic "^1.2.6" + globalthis "^1.0.4" + gopd "^1.2.0" + has-property-descriptors "^1.0.2" + has-proto "^1.2.0" + has-symbols "^1.1.0" + internal-slot "^1.1.0" + iterator.prototype "^1.1.4" + safe-array-concat "^1.1.3" + +es-module-lexer@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" + integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.0.3, es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +es-shim-unscopables@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz#438df35520dac5d105f3943d927549ea3b00f4b5" + integrity sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw== + dependencies: + hasown "^2.0.2" + +es-to-primitive@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" + integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== + dependencies: + is-callable "^1.2.7" + is-date-object "^1.0.5" + is-symbol "^1.0.4" + +es6-error@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + +esbuild@^0.25.0: + version "0.25.3" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.3.tgz#371f7cb41283e5b2191a96047a7a89562965a285" + integrity sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.3" + "@esbuild/android-arm" "0.25.3" + "@esbuild/android-arm64" "0.25.3" + "@esbuild/android-x64" "0.25.3" + "@esbuild/darwin-arm64" "0.25.3" + "@esbuild/darwin-x64" "0.25.3" + "@esbuild/freebsd-arm64" "0.25.3" + "@esbuild/freebsd-x64" "0.25.3" + "@esbuild/linux-arm" "0.25.3" + "@esbuild/linux-arm64" "0.25.3" + "@esbuild/linux-ia32" "0.25.3" + "@esbuild/linux-loong64" "0.25.3" + "@esbuild/linux-mips64el" "0.25.3" + "@esbuild/linux-ppc64" "0.25.3" + "@esbuild/linux-riscv64" "0.25.3" + "@esbuild/linux-s390x" "0.25.3" + "@esbuild/linux-x64" "0.25.3" + "@esbuild/netbsd-arm64" "0.25.3" + "@esbuild/netbsd-x64" "0.25.3" + "@esbuild/openbsd-arm64" "0.25.3" + "@esbuild/openbsd-x64" "0.25.3" + "@esbuild/sunos-x64" "0.25.3" + "@esbuild/win32-arm64" "0.25.3" + "@esbuild/win32-ia32" "0.25.3" + "@esbuild/win32-x64" "0.25.3" + +escalade@^3.1.1, escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-goat@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-4.0.0.tgz#9424820331b510b0666b98f7873fe11ac4aa8081" + integrity sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg== + +escape-html@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" + integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== + +eslint-plugin-react@^7.37.5: + version "7.37.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz#2975511472bdda1b272b34d779335c9b0e877065" + integrity sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA== + dependencies: + array-includes "^3.1.8" + array.prototype.findlast "^1.2.5" + array.prototype.flatmap "^1.3.3" + array.prototype.tosorted "^1.1.4" + doctrine "^2.1.0" + es-iterator-helpers "^1.2.1" + estraverse "^5.3.0" + hasown "^2.0.2" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.9" + object.fromentries "^2.0.8" + object.values "^1.2.1" + prop-types "^15.8.1" + resolve "^2.0.0-next.5" + semver "^6.3.1" + string.prototype.matchall "^4.0.12" + string.prototype.repeat "^1.0.0" + +eslint-scope@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.3.0.tgz#10cd3a918ffdd722f5f3f7b5b83db9b23c87340d" + integrity sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" + integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== + +eslint@^9.26.0: + version "9.26.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.26.0.tgz#978fe029adc2aceed28ab437bca876e83461c3b4" + integrity sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.20.0" + "@eslint/config-helpers" "^0.2.1" + "@eslint/core" "^0.13.0" + "@eslint/eslintrc" "^3.3.1" + "@eslint/js" "9.26.0" + "@eslint/plugin-kit" "^0.2.8" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.2" + "@modelcontextprotocol/sdk" "^1.8.0" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.6" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.3.0" + eslint-visitor-keys "^4.2.0" + espree "^10.3.0" + esquery "^1.5.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + 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" + json-stable-stringify-without-jsonify "^1.0.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + zod "^3.24.2" + +espree@^10.0.1, espree@^10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" + integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== + dependencies: + acorn "^8.14.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.0" + +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +estree-walker@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +eventsource-parser@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.1.tgz#5e358dba9a55ba64ca90da883c4ca35bd82467bd" + integrity sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA== + +eventsource@^3.0.2: + version "3.0.6" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-3.0.6.tgz#5c4b24cd70c0323eed2651a5ee07bd4bc391e656" + integrity sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA== + dependencies: + eventsource-parser "^3.0.1" + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +execa@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9" + integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" + +execa@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" + integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^8.0.1" + human-signals "^5.0.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^4.1.0" + strip-final-newline "^3.0.0" + +express-rate-limit@^7.5.0: + version "7.5.0" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.5.0.tgz#6a67990a724b4fbbc69119419feef50c51e8b28f" + integrity sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg== + +express@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/express/-/express-5.1.0.tgz#d31beaf715a0016f0d53f47d3b4d7acf28c75cc9" + integrity sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA== + dependencies: + accepts "^2.0.0" + body-parser "^2.2.0" + content-disposition "^1.0.0" + content-type "^1.0.5" + cookie "^0.7.1" + cookie-signature "^1.2.1" + debug "^4.4.0" + encodeurl "^2.0.0" + escape-html "^1.0.3" + etag "^1.8.1" + finalhandler "^2.1.0" + fresh "^2.0.0" + http-errors "^2.0.0" + merge-descriptors "^2.0.0" + mime-types "^3.0.0" + on-finished "^2.4.1" + once "^1.4.0" + parseurl "^1.3.3" + proxy-addr "^2.0.7" + qs "^6.14.0" + range-parser "^1.2.1" + router "^2.2.0" + send "^1.1.0" + serve-static "^2.2.0" + statuses "^2.0.1" + type-is "^2.0.1" + vary "^1.1.2" + +exsolve@^1.0.1, exsolve@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/exsolve/-/exsolve-1.0.5.tgz#1f5b6b4fe82ad6b28a173ccb955a635d77859dcf" + integrity sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg== + +extract-zip@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.3.2, fast-glob@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-redact@^3.1.1: + version "3.5.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" + integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== + +fastq@^1.6.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + dependencies: + reusify "^1.0.4" + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== + dependencies: + pend "~1.2.0" + +fdir@^6.4.4: + version "6.4.4" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.4.tgz#1cfcf86f875a883e19a8fab53622cfe992e8d2f9" + integrity sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg== + +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + +filesize@^10.1.6: + version "10.1.6" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-10.1.6.tgz#31194da825ac58689c0bce3948f33ce83aabd361" + integrity sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w== + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-2.1.0.tgz#72306373aa89d05a8242ed569ed86a1bff7c561f" + integrity sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q== + dependencies: + debug "^4.4.0" + encodeurl "^2.0.0" + escape-html "^1.0.3" + on-finished "^2.4.1" + parseurl "^1.3.3" + statuses "^2.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +firefox-profile@4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/firefox-profile/-/firefox-profile-4.7.0.tgz#97087b17a9a38fea58ec0acf2bca19a5cc121cb7" + integrity sha512-aGApEu5bfCNbA4PGUZiRJAIU6jKmghV2UVdklXAofnNtiDjqYw0czLS46W7IfFqVKgKhFB8Ao2YoNGHY4BoIMQ== + dependencies: + adm-zip "~0.5.x" + fs-extra "^11.2.0" + ini "^4.1.3" + minimist "^1.2.8" + xml2js "^0.6.2" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flatted@^3.2.9: + version "3.3.3" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" + integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== + +for-each@^0.3.3, for-each@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== + dependencies: + is-callable "^1.2.7" + +formdata-node@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-6.0.3.tgz#48f8e2206ae2befded82af621ef015f08168dc6d" + integrity sha512-8e1++BCiTzUno9v5IZ2J6bv4RU+3UKDmqWUQD0MIMVCd9AdhWkO1gw57oo1mNEX1dMq2EGI+FbWz4B92pscSQg== + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-2.0.0.tgz#8dd7df6a1b3a1b3a5cf186c05a5dd267622635a4" + integrity sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A== + +fs-extra@^11.2.0: + version "11.3.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d" + integrity sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78" + integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + functions-have-names "^1.2.3" + hasown "^2.0.2" + is-callable "^1.2.7" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +fx-runner@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/fx-runner/-/fx-runner-1.4.0.tgz#7a3f0374cc78c6c689ef75937b7b0cd75428c509" + integrity sha512-rci1g6U0rdTg6bAaBboP7XdRu01dzTAaKXxFf+PUqGuCv6Xu7o8NZdY1D5MvKGIjb6EdS1g3VlXOgksir1uGkg== + dependencies: + commander "2.9.0" + shell-quote "1.7.3" + spawn-sync "1.0.15" + when "3.7.7" + which "1.2.4" + winreg "0.0.12" + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-east-asian-width@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz#21b4071ee58ed04ee0db653371b55b4299875389" + integrity sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ== + +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-port-please@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-3.1.2.tgz#502795e56217128e4183025c89a48c71652f4e49" + integrity sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ== + +get-proto@^1.0.0, get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-stream@^6.0.0, get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-stream@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" + integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== + +get-symbol-description@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee" + integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + +giget@^1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/giget/-/giget-1.2.5.tgz#0bd4909356a0da75cc1f2b33538f93adec0d202f" + integrity sha512-r1ekGw/Bgpi3HLV3h1MRBIlSAdHoIMklpaQ3OQLFcRw9PwAj2rqigvIbg+dBUI51OxVI2jsEtDywDBjSiuf7Ug== + dependencies: + citty "^0.1.6" + consola "^3.4.0" + defu "^6.1.4" + node-fetch-native "^1.6.6" + nypm "^0.5.4" + pathe "^2.0.3" + tar "^6.2.1" + +giget@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/giget/-/giget-2.0.0.tgz#395fc934a43f9a7a29a29d55b99f23e30c14f195" + integrity sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA== + dependencies: + citty "^0.1.6" + consola "^3.4.0" + defu "^6.1.4" + node-fetch-native "^1.6.6" + nypm "^0.6.0" + pathe "^2.0.3" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +global-directory@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/global-directory/-/global-directory-4.0.1.tgz#4d7ac7cfd2cb73f304c53b8810891748df5e361e" + integrity sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q== + dependencies: + ini "4.1.1" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + +globals@^16.0.0: + version "16.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-16.0.0.tgz#3d7684652c5c4fbd086ec82f9448214da49382d8" + integrity sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A== + +globalthis@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== + dependencies: + define-properties "^1.2.1" + gopd "^1.0.1" + +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +graceful-fs@4.2.10: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +growly@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" + integrity sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw== + +has-bigints@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" + integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5" + integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== + dependencies: + dunder-proto "^1.0.0" + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +highlight.js@^10.7.1: + version "10.7.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== + +hookable@^5.5.3: + version "5.5.3" + resolved "https://registry.yarnpkg.com/hookable/-/hookable-5.5.3.tgz#6cfc358984a1ef991e2518cb9ed4a778bbd3215d" + integrity sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ== + +html-escaper@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-3.0.3.tgz#4d336674652beb1dcbc29ef6b6ba7f6be6fdfed6" + integrity sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ== + +htmlparser2@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-10.0.0.tgz#77ad249037b66bf8cc99c6e286ef73b83aeb621d" + integrity sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.2.1" + entities "^6.0.0" + +http-errors@2.0.0, http-errors@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== + +human-signals@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" + integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== + +iconv-lite@0.6.3, iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^5.2.0, ignore@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + +import-fresh@^3.2.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-meta-resolve@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz#f9db8bead9fafa61adb811db77a2bf22c5399706" + integrity sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" + integrity sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g== + +ini@^1.3.4, ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +ini@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.3.tgz#4c359675a6071a46985eb39b14e4a2c0ec98a795" + integrity sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg== + +internal-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" + integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== + dependencies: + es-errors "^1.3.0" + hasown "^2.0.2" + side-channel "^1.1.0" + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-absolute@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-0.1.7.tgz#847491119fccb5fb436217cc737f7faad50f603f" + integrity sha512-Xi9/ZSn4NFapG8RP98iNPMOeaV3mXPisxKxzKtHVqr3g56j/fBn+yZmnxSVAA8lmZbl2J9b/a4kJvfU3hqQYgA== + dependencies: + is-relative "^0.1.0" + +is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" + integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-async-function@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.1.tgz#3e69018c8e04e73b738793d020bfe884b9fd3523" + integrity sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ== + dependencies: + async-function "^1.0.0" + call-bound "^1.0.3" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-bigint@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672" + integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== + dependencies: + has-bigints "^1.0.2" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.2.tgz#7067f47709809a393c71ff5bb3e135d8a9215d9e" + integrity sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.13.0: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + +is-data-view@^1.0.1, is-data-view@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e" + integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw== + dependencies: + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + is-typed-array "^1.1.13" + +is-date-object@^1.0.5, is-date-object@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" + integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finalizationregistry@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90" + integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== + dependencies: + call-bound "^1.0.3" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-fullwidth-code-point@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" + integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + +is-fullwidth-code-point@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz#9609efced7c2f97da7b60145ef481c787c7ba704" + integrity sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA== + dependencies: + get-east-asian-width "^1.0.0" + +is-generator-function@^1.0.10: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca" + integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ== + dependencies: + call-bound "^1.0.3" + get-proto "^1.0.0" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-in-ci@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-in-ci/-/is-in-ci-1.0.0.tgz#9a86bbda7e42c6129902e0574c54b018fbb6ab88" + integrity sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg== + +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + +is-installed-globally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-1.0.0.tgz#08952c43758c33d815692392f7f8437b9e436d5a" + integrity sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ== + dependencies: + global-directory "^4.0.1" + is-path-inside "^4.0.0" + +is-interactive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90" + integrity sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ== + +is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== + +is-npm@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-6.0.0.tgz#b59e75e8915543ca5d881ecff864077cba095261" + integrity sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ== + +is-number-object@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" + integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-4.0.0.tgz#805aeb62c47c1b12fc3fd13bfb3ed1e7430071db" + integrity sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + +is-primitive@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-3.0.1.tgz#98c4db1abff185485a657fc2905052b940524d05" + integrity sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w== + +is-promise@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" + integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== + +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== + dependencies: + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +is-relative@^0.1.0: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.1.3.tgz#905fee8ae86f45b3ec614bc3c15c869df0876e82" + integrity sha512-wBOr+rNM4gkAZqoLRJI4myw5WzzIdQosFAAbnvfXP5z1LyzgAI3ivOKehC5KfqlQJZoihVhirgtCBj378Eg8GA== + +is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== + +is-shared-array-buffer@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f" + integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A== + dependencies: + call-bound "^1.0.3" + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + +is-string@^1.0.7, is-string@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" + integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-symbol@^1.0.4, is-symbol@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" + integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== + dependencies: + call-bound "^1.0.2" + has-symbols "^1.1.0" + safe-regex-test "^1.1.0" + +is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== + dependencies: + which-typed-array "^1.1.16" + +is-unicode-supported@^1.1.0, is-unicode-supported@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz#d824984b616c292a2e198207d4a609983842f714" + integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ== + +is-unicode-supported@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz#09f0ab0de6d3744d48d265ebb98f65d11f2a9b3a" + integrity sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ== + +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== + +is-weakref@^1.0.2, is-weakref@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.1.tgz#eea430182be8d64174bd96bffbc46f21bf3f9293" + integrity sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew== + dependencies: + call-bound "^1.0.3" + +is-weakset@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca" + integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== + dependencies: + call-bound "^1.0.3" + get-intrinsic "^1.2.6" + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +is-wsl@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" + integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== + dependencies: + is-inside-container "^1.0.0" + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0" + integrity sha512-d2eJzK691yZwPHcv1LbeAOa91yMJ9QmfTgSO1oXB65ezVhXQsxBac2vEB4bMVms9cGzaA99n6V2viHMq82VLDw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +iterator.prototype@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.5.tgz#12c959a29de32de0aa3bbbb801f4d777066dae39" + integrity sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g== + dependencies: + define-data-property "^1.1.4" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.6" + get-proto "^1.0.0" + has-symbols "^1.1.0" + set-function-name "^2.0.2" + +jiti@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560" + integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.1.tgz#2ec43964658435296f6761b34e10671c2d9527f4" + integrity sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz#b43d35e89c0f3be6b5fbbe9dc6c82467b30c28da" + integrity sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +"jsx-ast-utils@^2.4.1 || ^3.0.0": + version "3.3.5" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== + dependencies: + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + object.assign "^4.1.4" + object.values "^1.1.6" + +jszip@^3.10.1, jszip@^3.2.2: + version "3.10.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== + dependencies: + lie "~3.3.0" + pako "~1.0.2" + readable-stream "~2.3.6" + setimmediate "^1.0.5" + +keyborg@2.6.0, keyborg@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/keyborg/-/keyborg-2.6.0.tgz#ebfcaaed2f517f9295058ff5d57d14e71958ab5a" + integrity sha512-o5kvLbuTF+o326CMVYpjlaykxqYP9DphFQZ2ZpgrvBouyvOxyEB7oqe8nOLFpiV5VCtz0D3pt8gXQYWpLpBnmA== + +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +ky@^1.2.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/ky/-/ky-1.8.1.tgz#b1adaa473bc30aced2bab4c408ec177b78d198f0" + integrity sha512-7Bp3TpsE+L+TARSnnDpk3xg8Idi8RwSLdj6CMbNWoOARIrGrbuLGusV0dYwbZOm4bB3jHNxSw8Wk/ByDqJEnDw== + +latest-version@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-9.0.0.tgz#e91ed216e7a4badc6f73b66c65adb46c58ec6ba1" + integrity sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA== + dependencies: + package-json "^10.0.0" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lie@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + +lighthouse-logger@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/lighthouse-logger/-/lighthouse-logger-2.0.1.tgz#48895f639b61cca89346bb6f47f7403a3895fa02" + integrity sha512-ioBrW3s2i97noEmnXxmUq7cjIcVRjT5HBpAYy8zE11CxU9HqlWHHeRxfeN1tn8F7OEMVPIC9x1f8t3Z7US9ehQ== + dependencies: + debug "^2.6.9" + marky "^1.2.2" + +lines-and-columns@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-2.0.4.tgz#d00318855905d2660d8c0822e3f5a4715855fc42" + integrity sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A== + +linkedom@^0.18.5: + version "0.18.10" + resolved "https://registry.yarnpkg.com/linkedom/-/linkedom-0.18.10.tgz#28c2e2ed26770f0d104f176404429d48dde8fb79" + integrity sha512-ESCqVAtme2GI3zZnlVRidiydByV6WmPlmKeFzFVQslADiAO2Wi+H6xL/5kr/pUOESjEoVb2Eb3cYFJ/TQhQOWA== + dependencies: + css-select "^5.1.0" + cssom "^0.5.0" + html-escaper "^3.0.3" + htmlparser2 "^10.0.0" + uhyphen "^0.2.0" + +listr2@^8.0.1: + version "8.3.2" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.3.2.tgz#c252ec9a3334950bfca9238457d0ad2c1a5cc867" + integrity sha512-vsBzcU4oE+v0lj4FhVLzr9dBTv4/fHIa57l+GCwovP8MoFNZJTOhGU8PXd4v2VJCbECAaijBiHntiekFMLvo0g== + dependencies: + cli-truncate "^4.0.0" + colorette "^2.0.20" + eventemitter3 "^5.0.1" + log-update "^6.1.0" + rfdc "^1.4.1" + wrap-ansi "^9.0.0" + +local-pkg@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-1.1.1.tgz#f5fe74a97a3bd3c165788ee08ca9fbe998dc58dd" + integrity sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg== + dependencies: + mlly "^1.7.4" + pkg-types "^2.0.1" + quansync "^0.2.8" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.kebabcase@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" + integrity sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.snakecase@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" + integrity sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw== + +log-symbols@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-5.1.0.tgz#a20e3b9a5f53fac6aeb8e2bb22c07cf2c8f16d93" + integrity sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA== + dependencies: + chalk "^5.0.0" + is-unicode-supported "^1.1.0" + +log-symbols@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-6.0.0.tgz#bb95e5f05322651cac30c0feb6404f9f2a8a9439" + integrity sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw== + dependencies: + chalk "^5.3.0" + is-unicode-supported "^1.3.0" + +log-update@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.1.0.tgz#1a04ff38166f94647ae1af562f4bd6a15b1b7cd4" + integrity sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w== + 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" + +loose-envify@^1.1.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lzutf8@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/lzutf8/-/lzutf8-0.6.3.tgz#37a2ebe80922a8405f1e3f24c6c2b74c3e430981" + integrity sha512-CAkF9HKrM+XpB0f3DepQ2to2iUEo0zrbh+XgBqgNBc1+k8HMM3u/YSfHI3Dr4GmoTIez2Pr/If1XFl3rU26AwA== + dependencies: + readable-stream "^4.0.0" + +magic-string@^0.30.17: + version "0.30.17" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" + integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + +magicast@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.5.tgz#8301c3c7d66704a0771eb1bad74274f0ec036739" + integrity sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ== + dependencies: + "@babel/parser" "^7.25.4" + "@babel/types" "^7.25.4" + source-map-js "^1.2.0" + +make-error@^1.3.2: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +many-keys-map@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/many-keys-map/-/many-keys-map-2.0.1.tgz#3ae9f97cff78e08f79311d4e9c42fb3cc583f61e" + integrity sha512-DHnZAD4phTbZ+qnJdjoNEVU1NecYoSdbOOoVmTDH46AuxDkEVh3MxTVpXq10GtcTC6mndN9dkv1rNfpjRcLnOw== + +marky@^1.2.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/marky/-/marky-1.3.0.tgz#422b63b0baf65022f02eda61a238eccdbbc14997" + integrity sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ== + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +mdn-data@2.20.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.20.0.tgz#b2274bafb8d1ce544bd040b9d427b8534010575d" + integrity sha512-/d3otgvmquUkAN2RVxSg6lIbQrYX7isR4aC5Hvw8JuHvzctR3eUG50WmsAZjb9MkbJ5LbijPSy7uIxEtQDGI0w== + +media-typer@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561" + integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw== + +merge-descriptors@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz#ea922f660635a2249ee565e0449f951e6b603808" + integrity sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@^1.54.0: + version "1.54.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" + integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== + +mime-types@^3.0.0, mime-types@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-3.0.1.tgz#b1d94d6997a9b32fd69ebaed0db73de8acb519ce" + integrity sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA== + dependencies: + mime-db "^1.54.0" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + +mimic-function@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mimic-function/-/mimic-function-5.0.1.tgz#acbe2b3349f99b9deaca7fb70e48b83e94e67076" + integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== + +minimatch@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b" + integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0, minimist@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mlly@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.4.tgz#3d7295ea2358ec7a271eaa5d000a0f84febe100f" + integrity sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw== + dependencies: + acorn "^8.14.0" + pathe "^2.0.1" + pkg-types "^1.3.0" + ufo "^1.5.4" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multimatch@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-6.0.0.tgz#c72a9bddbc94baa4727efd613b5d22a1fe4d6ee3" + integrity sha512-I7tSVxHGPlmPN/enE3mS1aOSo6bWBfls+3HmuEeCUBCE7gWnm3cBXCBkpurzFjVRwC6Kld8lLaZ1Iv5vOcjvcQ== + dependencies: + "@types/minimatch" "^3.0.5" + array-differ "^4.0.0" + array-union "^3.0.1" + minimatch "^3.0.4" + +mz@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nano-spawn@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/nano-spawn/-/nano-spawn-0.2.0.tgz#855cae42ac99caa6984aa2e9890bf191ef09994c" + integrity sha512-IjZBIOLxSlxu+m/kacg9JuP93oUpRemeV0mEuCy64nzBKKIL9m0aLJHtVPcVuzJDHFhElzjpwbW4a3tMzgKoZQ== + +nanoid@^3.3.8: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +negotiator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" + integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== + +node-fetch-native@^1.6.4, node-fetch-native@^1.6.6: + version "1.6.6" + resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.6.tgz#ae1d0e537af35c2c0b0de81cbff37eedd410aa37" + integrity sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ== + +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + +node-notifier@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-10.0.1.tgz#0e82014a15a8456c4cfcdb25858750399ae5f1c7" + integrity sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ== + dependencies: + growly "^1.3.0" + is-wsl "^2.2.0" + semver "^7.3.5" + shellwords "^0.1.1" + uuid "^8.3.2" + which "^2.0.2" + +node-releases@^2.0.19: + version "2.0.19" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" + integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +npm-run-path@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" + integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== + dependencies: + path-key "^4.0.0" + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +nypm@^0.3.12: + version "0.3.12" + resolved "https://registry.yarnpkg.com/nypm/-/nypm-0.3.12.tgz#37541bec0af3a37d3acd81d6662c6666e650b22e" + integrity sha512-D3pzNDWIvgA+7IORhD/IuWzEk4uXv6GsgOxiid4UU3h9oq5IqV1KtPDi63n4sZJ/xcWlr88c0QM2RgN5VbOhFA== + dependencies: + citty "^0.1.6" + consola "^3.2.3" + execa "^8.0.1" + pathe "^1.1.2" + pkg-types "^1.2.0" + ufo "^1.5.4" + +nypm@^0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/nypm/-/nypm-0.5.4.tgz#a5ab0d8d37f96342328479f88ef58699f29b3051" + integrity sha512-X0SNNrZiGU8/e/zAB7sCTtdxWTMSIO73q+xuKgglm2Yvzwlo8UoC5FNySQFCvl84uPaeADkqHUZUkWy4aH4xOA== + dependencies: + citty "^0.1.6" + consola "^3.4.0" + pathe "^2.0.3" + pkg-types "^1.3.1" + tinyexec "^0.3.2" + ufo "^1.5.4" + +nypm@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/nypm/-/nypm-0.6.0.tgz#3a04623d1c358a93fc4b3cb9cfb6a11af080feca" + integrity sha512-mn8wBFV9G9+UFHIrq+pZ2r2zL4aPau/by3kJb3cM7+5tQHMt6HGQB8FDIeKFYp8o0D2pnH6nVsO88N4AmUxIWg== + dependencies: + citty "^0.1.6" + consola "^3.4.0" + pathe "^2.0.3" + pkg-types "^2.0.0" + tinyexec "^0.3.2" + +object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.13.3: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4, object.assign@^4.1.7: + version "4.1.7" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== + 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" + +object.entries@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.9.tgz#e4770a6a1444afb61bd39f984018b5bede25f8b3" + integrity sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.4" + define-properties "^1.2.1" + es-object-atoms "^1.1.1" + +object.fromentries@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" + integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + +object.values@^1.1.6, object.values@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.1.tgz#deed520a50809ff7f75a7cfd4bc64c7a038c6216" + integrity sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +ofetch@^1.3.3: + version "1.4.1" + resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.4.1.tgz#b6bf6b0d75ba616cef6519dd8b6385a8bae480ec" + integrity sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw== + dependencies: + destr "^2.0.3" + node-fetch-native "^1.6.4" + ufo "^1.5.4" + +ohash@^1.1.4: + version "1.1.6" + resolved "https://registry.yarnpkg.com/ohash/-/ohash-1.1.6.tgz#9ff7b0271d7076290794537d68ec2b40a60d133e" + integrity sha512-TBu7PtV8YkAZn0tSxobKY2n2aAQva936lhRrj6957aDaCf9IEtqsKbgMzXE/F/sjqYOwmrukeORHNLe5glk7Cg== + +ohash@^2.0.11: + version "2.0.11" + resolved "https://registry.yarnpkg.com/ohash/-/ohash-2.0.11.tgz#60b11e8cff62ca9dee88d13747a5baa145f5900b" + integrity sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ== + +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + +on-finished@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.0, onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +onetime@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-7.0.0.tgz#9f16c92d8c9ef5120e3acd9dd9957cceecc1ab60" + integrity sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ== + dependencies: + mimic-function "^5.0.0" + +open@^10.1.0: + version "10.1.2" + resolved "https://registry.yarnpkg.com/open/-/open-10.1.2.tgz#d5df40984755c9a9c3c93df8156a12467e882925" + integrity sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw== + dependencies: + default-browser "^5.2.1" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^3.1.0" + +open@^8.4.0: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +open@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-9.1.0.tgz#684934359c90ad25742f5a26151970ff8c6c80b6" + integrity sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg== + dependencies: + default-browser "^4.0.0" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^2.2.0" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + 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" + +ora@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-6.3.1.tgz#a4e9e5c2cf5ee73c259e8b410273e706a2ad3ed6" + integrity sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ== + dependencies: + chalk "^5.0.0" + cli-cursor "^4.0.0" + cli-spinners "^2.6.1" + is-interactive "^2.0.0" + is-unicode-supported "^1.1.0" + log-symbols "^5.1.0" + stdin-discarder "^0.1.0" + strip-ansi "^7.0.1" + wcwidth "^1.0.1" + +ora@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-8.2.0.tgz#8fbbb7151afe33b540dd153f171ffa8bd38e9861" + integrity sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw== + dependencies: + chalk "^5.3.0" + cli-cursor "^5.0.0" + cli-spinners "^2.9.2" + is-interactive "^2.0.0" + is-unicode-supported "^2.0.0" + log-symbols "^6.0.0" + stdin-discarder "^0.2.2" + string-width "^7.2.0" + strip-ansi "^7.1.0" + +os-shim@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" + integrity sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A== + +own-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358" + integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg== + dependencies: + get-intrinsic "^1.2.6" + object-keys "^1.1.1" + safe-push-apply "^1.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +package-json@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-10.0.1.tgz#e49ee07b8de63b638e7f1b5bb353733e428fe7d7" + integrity sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg== + dependencies: + ky "^1.2.0" + registry-auth-token "^5.0.2" + registry-url "^6.0.1" + semver "^7.6.0" + +pako@~1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-7.1.1.tgz#68f7e6f0edf88c54ab14c00eb700b753b14e2120" + integrity sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw== + dependencies: + "@babel/code-frame" "^7.21.4" + error-ex "^1.3.2" + json-parse-even-better-errors "^3.0.0" + lines-and-columns "^2.0.3" + type-fest "^3.8.0" + +parse5-htmlparser2-tree-adapter@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" + integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== + dependencies: + parse5 "^6.0.1" + +parse5@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== + +parse5@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +parseurl@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.2.0.tgz#73990cc29e57a3ff2a0d914095156df5db79e8b4" + integrity sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ== + +pathe@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" + integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== + +pathe@^2.0.1, pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== + +perfect-debounce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz#9c2e8bc30b169cc984a58b7d5b28049839591d2a" + integrity sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + +pino-abstract-transport@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz#de241578406ac7b8a33ce0d77ae6e8a0b3b68a60" + integrity sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw== + dependencies: + split2 "^4.0.0" + +pino-std-serializers@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b" + integrity sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA== + +pino@9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-9.6.0.tgz#6bc628159ba0cc81806d286718903b7fc6b13169" + integrity sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg== + dependencies: + atomic-sleep "^1.0.0" + fast-redact "^3.1.1" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^2.0.0" + pino-std-serializers "^7.0.0" + process-warning "^4.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.2.0" + safe-stable-stringify "^2.3.1" + sonic-boom "^4.0.1" + thread-stream "^3.0.0" + +pkce-challenge@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pkce-challenge/-/pkce-challenge-5.0.0.tgz#c3a405cb49e272094a38e890a2b51da0228c4d97" + integrity sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ== + +pkg-types@^1.2.0, pkg-types@^1.3.0, pkg-types@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.3.1.tgz#bd7cc70881192777eef5326c19deb46e890917df" + integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== + dependencies: + confbox "^0.1.8" + mlly "^1.7.4" + pathe "^2.0.1" + +pkg-types@^2.0.0, pkg-types@^2.0.1, pkg-types@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-2.1.0.tgz#70c9e1b9c74b63fdde749876ee0aa007ea9edead" + integrity sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A== + dependencies: + confbox "^0.2.1" + exsolve "^1.0.1" + pathe "^2.0.3" + +possible-typed-array-names@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + +postcss@^8.5.3: + version "8.5.3" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" + integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== + dependencies: + nanoid "^3.3.8" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process-warning@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-4.0.1.tgz#5c1db66007c67c756e4e09eb170cdece15da32fb" + integrity sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + +promise-toolbox@0.21.0: + version "0.21.0" + resolved "https://registry.yarnpkg.com/promise-toolbox/-/promise-toolbox-0.21.0.tgz#6919876f9dea375f01b4ddaec4206db83cb0aa55" + integrity sha512-NV8aTmpwrZv+Iys54sSFOBx3tuVaOBvvrft5PNppnxy9xpU/akHbaWIril22AB22zaPgrgwKdD0KsrM0ptUtpg== + dependencies: + make-error "^1.3.2" + +prompts@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +prop-types@^15.6.2, prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== + +proxy-addr@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +"publish-browser-extension@^2.3.0 || ^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/publish-browser-extension/-/publish-browser-extension-3.0.0.tgz#938e226a10a10a995e83b5552a69337679a9204c" + integrity sha512-gwjH8mIepNqID2VqKIxzT6lmtvkcc5tcWYzrGSUdkeUFFFSHhGp9xx01EZ7j8wPq50dDe0XU5VNbHMAqr6wWAA== + dependencies: + cac "^6.7.14" + cli-highlight "^2.1.11" + consola "^3.2.3" + dotenv "^16.3.1" + extract-zip "^2.0.1" + formdata-node "^6.0.3" + listr2 "^8.0.1" + lodash.camelcase "^4.3.0" + lodash.kebabcase "^4.1.1" + lodash.snakecase "^4.1.1" + ofetch "^1.3.3" + open "^9.1.0" + ora "^6.3.1" + prompts "^2.4.2" + zod "^3.22.4" + +pump@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8" + integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +pupa@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pupa/-/pupa-3.1.0.tgz#f15610274376bbcc70c9a3aa8b505ea23f41c579" + integrity sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug== + dependencies: + escape-goat "^4.0.0" + +qs@^6.14.0: + version "6.14.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" + integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== + dependencies: + side-channel "^1.1.0" + +quansync@^0.2.8: + version "0.2.10" + resolved "https://registry.yarnpkg.com/quansync/-/quansync-0.2.10.tgz#32053cf166fa36511aae95fc49796116f2dc20e1" + integrity sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + +range-parser@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.0.tgz#25b3476f07a51600619dae3fe82ddc28a36e5e0f" + integrity sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.6.3" + unpipe "1.0.0" + +rc9@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/rc9/-/rc9-2.1.2.tgz#6282ff638a50caa0a91a31d76af4a0b9cbd1080d" + integrity sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg== + dependencies: + defu "^6.1.4" + destr "^2.0.3" + +rc@1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-dom@18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.2" + +react-is@^16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-is@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-refresh@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.17.0.tgz#b7e579c3657f23d04eccbe4ad2e58a8ed51e7e53" + integrity sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ== + +react-transition-group@^4.4.1: + version "4.4.5" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" + integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + +react@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== + dependencies: + loose-envify "^1.1.0" + +readable-stream@^2.2.2, readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + 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" + +readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@^4.0.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91" + integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +real-require@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== + +reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" + integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.9" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.7" + get-proto "^1.0.1" + which-builtin-type "^1.2.1" + +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + +regexp.prototype.flags@^1.5.3: + version "1.5.4" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19" + integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-errors "^1.3.0" + get-proto "^1.0.1" + gopd "^1.2.0" + set-function-name "^2.0.2" + +registry-auth-token@^5.0.2: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-5.1.0.tgz#3c659047ecd4caebd25bc1570a3aa979ae490eca" + integrity sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw== + dependencies: + "@pnpm/npm-conf" "^2.1.0" + +registry-url@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-6.0.1.tgz#056d9343680f2f64400032b1e199faa692286c58" + integrity sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q== + dependencies: + rc "1.2.8" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^2.0.0-next.5: + version "2.0.0-next.5" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +restore-cursor@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" + integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +restore-cursor@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-5.1.0.tgz#0766d95699efacb14150993f55baf0953ea1ebe7" + integrity sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA== + dependencies: + onetime "^7.0.0" + signal-exit "^4.1.0" + +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +rfdc@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== + +rollup@^4.34.9: + version "4.40.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.40.1.tgz#03d6c53ebb6a9c2c060ae686a61e72a2472b366f" + integrity sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw== + dependencies: + "@types/estree" "1.0.7" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.40.1" + "@rollup/rollup-android-arm64" "4.40.1" + "@rollup/rollup-darwin-arm64" "4.40.1" + "@rollup/rollup-darwin-x64" "4.40.1" + "@rollup/rollup-freebsd-arm64" "4.40.1" + "@rollup/rollup-freebsd-x64" "4.40.1" + "@rollup/rollup-linux-arm-gnueabihf" "4.40.1" + "@rollup/rollup-linux-arm-musleabihf" "4.40.1" + "@rollup/rollup-linux-arm64-gnu" "4.40.1" + "@rollup/rollup-linux-arm64-musl" "4.40.1" + "@rollup/rollup-linux-loongarch64-gnu" "4.40.1" + "@rollup/rollup-linux-powerpc64le-gnu" "4.40.1" + "@rollup/rollup-linux-riscv64-gnu" "4.40.1" + "@rollup/rollup-linux-riscv64-musl" "4.40.1" + "@rollup/rollup-linux-s390x-gnu" "4.40.1" + "@rollup/rollup-linux-x64-gnu" "4.40.1" + "@rollup/rollup-linux-x64-musl" "4.40.1" + "@rollup/rollup-win32-arm64-msvc" "4.40.1" + "@rollup/rollup-win32-ia32-msvc" "4.40.1" + "@rollup/rollup-win32-x64-msvc" "4.40.1" + fsevents "~2.3.2" + +router@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/router/-/router-2.2.0.tgz#019be620b711c87641167cc79b99090f00b146ef" + integrity sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ== + dependencies: + debug "^4.4.0" + depd "^2.0.0" + is-promise "^4.0.0" + parseurl "^1.3.3" + path-to-regexp "^8.0.0" + +rtl-css-js@^1.16.1: + version "1.16.1" + resolved "https://registry.yarnpkg.com/rtl-css-js/-/rtl-css-js-1.16.1.tgz#4b48b4354b0ff917a30488d95100fbf7219a3e80" + integrity sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg== + dependencies: + "@babel/runtime" "^7.1.2" + +run-applescript@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c" + integrity sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg== + dependencies: + execa "^5.0.0" + +run-applescript@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-7.0.0.tgz#e5a553c2bffd620e169d276c1cd8f1b64778fbeb" + integrity sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-array-concat@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" + integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + has-symbols "^1.1.0" + isarray "^2.0.5" + +safe-buffer@5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-push-apply@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5" + integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA== + dependencies: + es-errors "^1.3.0" + isarray "^2.0.5" + +safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" + +safe-stable-stringify@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@>=0.6.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" + integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== + +scheduler@0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" + integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== + dependencies: + loose-envify "^1.1.0" + +scheduler@^0.23.2: + version "0.23.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== + dependencies: + loose-envify "^1.1.0" + +scule@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/scule/-/scule-1.3.0.tgz#6efbd22fd0bb801bdcc585c89266a7d2daa8fbd3" + integrity sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.5, semver@^7.6.0, semver@^7.6.3: + version "7.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + +send@^1.1.0, send@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/send/-/send-1.2.0.tgz#32a7554fb777b831dfa828370f773a3808d37212" + integrity sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw== + dependencies: + debug "^4.3.5" + encodeurl "^2.0.0" + escape-html "^1.0.3" + etag "^1.8.1" + fresh "^2.0.0" + http-errors "^2.0.0" + mime-types "^3.0.1" + ms "^2.1.3" + on-finished "^2.4.1" + range-parser "^1.2.1" + statuses "^2.0.1" + +serialize-error@^11.0.0: + version "11.0.3" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-11.0.3.tgz#b54f439e15da5b4961340fbbd376b6b04aa52e92" + integrity sha512-2G2y++21dhj2R7iHAdd0FIzjGwuKZld+7Pl/bTU6YIkrC2ZMbVUjm+luj6A6V34Rv9XfKJDKpTWu9W4Gse1D9g== + dependencies: + type-fest "^2.12.2" + +serve-static@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.2.0.tgz#9c02564ee259bdd2251b82d659a2e7e1938d66f9" + integrity sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ== + dependencies: + encodeurl "^2.0.0" + escape-html "^1.0.3" + parseurl "^1.3.3" + send "^1.2.0" + +set-function-length@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +set-function-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.2" + +set-proto@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e" + integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw== + dependencies: + dunder-proto "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + +set-value@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-4.1.0.tgz#aa433662d87081b75ad88a4743bd450f044e7d09" + integrity sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw== + dependencies: + is-plain-object "^2.0.4" + is-primitive "^3.0.1" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" + integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== + +shellwords@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" + integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== + +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + +signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slice-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" + integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== + dependencies: + ansi-styles "^6.0.0" + is-fullwidth-code-point "^4.0.0" + +slice-ansi@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.0.tgz#cd6b4655e298a8d1bdeb04250a433094b347b9a9" + integrity sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg== + dependencies: + ansi-styles "^6.2.1" + is-fullwidth-code-point "^5.0.0" + +sonic-boom@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.0.tgz#e59a525f831210fa4ef1896428338641ac1c124d" + integrity sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww== + dependencies: + atomic-sleep "^1.0.0" + +source-map-js@^1.0.1, source-map-js@^1.2.0, source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +source-map-support@0.5.21: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +spawn-sync@1.0.15: + version "1.0.15" + resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" + integrity sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw== + dependencies: + concat-stream "^1.4.7" + os-shim "^0.1.2" + +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + +split@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== + dependencies: + through "2" + +statuses@2.0.1, statuses@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +stdin-discarder@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz#22b3e400393a8e28ebf53f9958f3880622efde21" + integrity sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ== + dependencies: + bl "^5.0.0" + +stdin-discarder@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.2.2.tgz#390037f44c4ae1a1ae535c5fe38dc3aba8d997be" + integrity sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ== + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^7.0.0, string-width@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" + integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== + dependencies: + emoji-regex "^10.3.0" + get-east-asian-width "^1.0.0" + strip-ansi "^7.1.0" + +string.prototype.matchall@^4.0.12: + version "4.0.12" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz#6c88740e49ad4956b1332a911e949583a275d4c0" + integrity sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-abstract "^1.23.6" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.6" + gopd "^1.2.0" + has-symbols "^1.1.0" + internal-slot "^1.1.0" + regexp.prototype.flags "^1.5.3" + set-function-name "^2.0.2" + side-channel "^1.1.0" + +string.prototype.repeat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz#e90872ee0308b29435aa26275f6e1b762daee01a" + integrity sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trim@^1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" + integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-data-property "^1.1.4" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-object-atoms "^1.0.0" + has-property-descriptors "^1.0.2" + +string.prototype.trimend@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" + integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string_decoder@^1.1.1, string_decoder@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1, strip-ansi@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-bom@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-5.0.0.tgz#88d2e135d154dca7a5e06b4a4ba9653b6bdc0dd2" + integrity sha512-p+byADHF7SzEcVnLvc/r3uognM1hUhObuHXxJcgLCfD194XAkaLbjq3Wzb0N5G2tgIjH0dgT708Z51QxMeu60A== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + +strip-json-comments@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-5.0.1.tgz#0d8b7d01b23848ed7dbdf4baaaa31a8250d8cfa0" + integrity sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +strip-literal@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-2.1.1.tgz#26906e65f606d49f748454a08084e94190c2e5ad" + integrity sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q== + dependencies: + js-tokens "^9.0.1" + +stubborn-fs@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/stubborn-fs/-/stubborn-fs-1.2.5.tgz#e5e244223166921ddf66ed5e062b6b3bf285bfd2" + integrity sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g== + +stylis@^4.2.0: + version "4.3.6" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.6.tgz#7c7b97191cb4f195f03ecab7d52f7902ed378320" + integrity sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tabster@^8.5.0: + version "8.5.4" + resolved "https://registry.yarnpkg.com/tabster/-/tabster-8.5.4.tgz#c4455e140ffeeb1f13883f194ba6f5c2d495a017" + integrity sha512-5Fe8vonlp6wjkBuaU3YImZsFncXkdxhCIE6CR28nD0n84kZERIDr9T9wBeya5h1Oj19AhzGFWyZrL6/29tCobA== + dependencies: + keyborg "2.6.0" + tslib "^2.3.1" + +tar@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + +thread-stream@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1" + integrity sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A== + dependencies: + real-require "^0.2.0" + +through@2: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + +tinyexec@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" + integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== + +tinyglobby@^0.2.13: + version "0.2.13" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.13.tgz#a0e46515ce6cbcd65331537e57484af5a7b2ff7e" + integrity sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw== + dependencies: + fdir "^6.4.4" + picomatch "^4.0.2" + +titleize@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" + integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ== + +tmp@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +ts-api-utils@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" + integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== + +tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.8.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^2.12.2: + version "2.19.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + +type-fest@^3.8.0: + version "3.13.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.13.1.tgz#bb744c1f0678bea7543a2d1ec24e83e68e8c8706" + integrity sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g== + +type-fest@^4.18.2, type-fest@^4.21.0: + version "4.40.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.40.1.tgz#d78a09f08dd1081a434dd377967650cfd565401d" + integrity sha512-9YvLNnORDpI+vghLU/Nf+zSv0kL47KbVJ1o3sKgoTefl6i+zebxbiDQWoe/oWWqPhIgQdRZRT1KA9sCPL810SA== + +type-is@^2.0.0, type-is@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-2.0.1.tgz#64f6cf03f92fce4015c2b224793f6bdd4b068c97" + integrity sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw== + dependencies: + content-type "^1.0.5" + media-typer "^1.1.0" + mime-types "^3.0.0" + +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-typed-array "^1.1.14" + +typed-array-byte-length@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce" + integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg== + dependencies: + call-bind "^1.0.8" + for-each "^0.3.3" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.14" + +typed-array-byte-offset@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz#ae3698b8ec91a8ab945016108aef00d5bff12355" + integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + for-each "^0.3.3" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.15" + reflect.getprototypeof "^1.0.9" + +typed-array-length@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" + integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" + reflect.getprototypeof "^1.0.6" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + +typescript-eslint@^8.31.1: + version "8.31.1" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.31.1.tgz#b77ab1e48ced2daab9225ff94bab54391a4af69b" + integrity sha512-j6DsEotD/fH39qKzXTQRwYYWlt7D+0HmfpOK+DVhwJOFLcdmn92hq3mBb7HlKJHbjjI/gTOqEcc9d6JfpFf/VA== + dependencies: + "@typescript-eslint/eslint-plugin" "8.31.1" + "@typescript-eslint/parser" "8.31.1" + "@typescript-eslint/utils" "8.31.1" + +typescript@^5.8.3: + version "5.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" + integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== + +ufo@^1.5.4: + version "1.6.1" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.6.1.tgz#ac2db1d54614d1b22c1d603e3aef44a85d8f146b" + integrity sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA== + +uhyphen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/uhyphen/-/uhyphen-0.2.0.tgz#8fdf0623314486e020a3c00ee5cc7a12fe722b81" + integrity sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA== + +uid@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/uid/-/uid-2.0.2.tgz#4b5782abf0f2feeefc00fa88006b2b3b7af3e3b9" + integrity sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g== + dependencies: + "@lukeed/csprng" "^1.0.0" + +unbox-primitive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2" + integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== + dependencies: + call-bound "^1.0.3" + has-bigints "^1.0.2" + has-symbols "^1.1.0" + which-boxed-primitive "^1.1.1" + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +unimport@^3.13.1: + version "3.14.6" + resolved "https://registry.yarnpkg.com/unimport/-/unimport-3.14.6.tgz#f01170aa2fb94c4f97b22c0ac2822ef7e8e0726d" + integrity sha512-CYvbDaTT04Rh8bmD8jz3WPmHYZRG/NnvYVzwD6V1YAlvvKROlAeNDUBhkBGzNav2RKaeuXvlWYaa1V4Lfi/O0g== + dependencies: + "@rollup/pluginutils" "^5.1.4" + acorn "^8.14.0" + escape-string-regexp "^5.0.0" + estree-walker "^3.0.3" + fast-glob "^3.3.3" + local-pkg "^1.0.0" + magic-string "^0.30.17" + mlly "^1.7.4" + pathe "^2.0.1" + picomatch "^4.0.2" + pkg-types "^1.3.0" + scule "^1.3.0" + strip-literal "^2.1.1" + unplugin "^1.16.1" + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +unpipe@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +unplugin@^1.16.1: + version "1.16.1" + resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.16.1.tgz#a844d2e3c3b14a4ac2945c42be80409321b61199" + integrity sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w== + dependencies: + acorn "^8.14.0" + webpack-virtual-modules "^0.6.2" + +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + +update-browserslist-db@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" + integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + +update-notifier@7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-7.3.1.tgz#49af1ad6acfa0ea01c0d0f3c04047c154ead7096" + integrity sha512-+dwUY4L35XFYEzE+OAL3sarJdUioVovq+8f7lcIJ7wnmnYQV5UD1Y/lcwaMSyaQ6Bj3JMj1XSTjZbNLHn/19yA== + dependencies: + boxen "^8.0.1" + chalk "^5.3.0" + configstore "^7.0.0" + is-in-ci "^1.0.0" + is-installed-globally "^1.0.0" + is-npm "^6.0.0" + latest-version "^9.0.0" + pupa "^3.1.0" + semver "^7.6.3" + xdg-basedir "^5.1.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +use-disposable@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/use-disposable/-/use-disposable-1.0.4.tgz#9fb7b0cd4828fc8a271be16c136daefa2fd9ebca" + integrity sha512-j83t6AMLWUyb5zwlTDqf6dP9LezM9R0yTbI/b6olmdaGtCKQUe9pgJWV6dRaaQLcozypjIEp4EmZr2DkZGKLSg== + +use-sync-external-store@^1.2.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz#55122e2a3edd2a6c106174c27485e0fd59bcfca0" + integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +vary@^1, vary@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +"vite-node@^2.1.4 || ^3.0.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-3.1.2.tgz#b17869a12307f5260b20ba4b58cf493afee70aa7" + integrity sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA== + dependencies: + cac "^6.7.14" + debug "^4.4.0" + es-module-lexer "^1.6.0" + pathe "^2.0.3" + vite "^5.0.0 || ^6.0.0" + +"vite@^5.0.0 || ^6.0.0", vite@^6.3.4: + version "6.3.4" + resolved "https://registry.yarnpkg.com/vite/-/vite-6.3.4.tgz#d441a72c7cd9a93b719bb851250a4e6c119c9cff" + integrity sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw== + dependencies: + esbuild "^0.25.0" + fdir "^6.4.4" + picomatch "^4.0.2" + postcss "^8.5.3" + rollup "^4.34.9" + tinyglobby "^0.2.13" + optionalDependencies: + fsevents "~2.3.3" + +watchpack@2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da" + integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + +web-ext-run@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/web-ext-run/-/web-ext-run-0.2.3.tgz#a1d997c94a499a49f41a65050fa41c02700930bd" + integrity sha512-u/IiZaZ7dHFqTM1MLF27rBy8mS9fEEsqoOKL0u+kQdOLmEioA/0Szp67ADd3WAJZLd8/hO8cFST1IC/YMXKIjQ== + dependencies: + "@babel/runtime" "7.27.0" + "@devicefarmer/adbkit" "3.3.8" + chrome-launcher "1.1.2" + debounce "1.2.1" + es6-error "4.1.1" + firefox-profile "4.7.0" + fx-runner "1.4.0" + multimatch "6.0.0" + node-notifier "10.0.1" + parse-json "7.1.1" + pino "9.6.0" + promise-toolbox "0.21.0" + set-value "4.1.0" + source-map-support "0.5.21" + strip-bom "5.0.0" + strip-json-comments "5.0.1" + tmp "0.2.3" + update-notifier "7.3.1" + watchpack "2.4.2" + ws "8.18.1" + zip-dir "2.0.0" + +webextension-polyfill@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz#ccb28101c910ba8cf955f7e6a263e662d744dbb8" + integrity sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g== + +webextension-polyfill@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/webextension-polyfill/-/webextension-polyfill-0.12.0.tgz#f62c57d2cd42524e9fbdcee494c034cae34a3d69" + integrity sha512-97TBmpoWJEE+3nFBQ4VocyCdLKfw54rFaJ6EVQYLBCXqCIpLSZkwGgASpv4oPt9gdKCJ80RJlcmNzNn008Ag6Q== + +webpack-virtual-modules@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz#057faa9065c8acf48f24cb57ac0e77739ab9a7e8" + integrity sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ== + +when-exit@^2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/when-exit/-/when-exit-2.1.4.tgz#e2a0e998f7ad67eb0d2ce37e9794386663cc96f7" + integrity sha512-4rnvd3A1t16PWzrBUcSDZqcAmsUIy4minDXT/CZ8F2mVDgd65i4Aalimgz1aQkRGU0iH5eT5+6Rx2TK8o443Pg== + +when@3.7.7: + version "3.7.7" + resolved "https://registry.yarnpkg.com/when/-/when-3.7.7.tgz#aba03fc3bb736d6c88b091d013d8a8e590d84718" + integrity sha512-9lFZp/KHoqH6bPKjbWqa+3Dg/K/r2v0X/3/G2x4DBGchVS2QX2VXL3cZV994WQVnTM1/PD71Az25nAzryEUugw== + +which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" + integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== + dependencies: + is-bigint "^1.1.0" + is-boolean-object "^1.2.1" + is-number-object "^1.1.1" + is-string "^1.1.1" + is-symbol "^1.1.1" + +which-builtin-type@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e" + integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== + dependencies: + call-bound "^1.0.2" + function.prototype.name "^1.1.6" + has-tostringtag "^1.0.2" + is-async-function "^2.0.0" + is-date-object "^1.1.0" + is-finalizationregistry "^1.1.0" + is-generator-function "^1.0.10" + is-regex "^1.2.1" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.1.0" + which-collection "^1.0.2" + which-typed-array "^1.1.16" + +which-collection@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== + dependencies: + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" + +which-typed-array@^1.1.16, which-typed-array@^1.1.18: + version "1.1.19" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956" + integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + for-each "^0.3.5" + get-proto "^1.0.1" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + +which@1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/which/-/which-1.2.4.tgz#1557f96080604e5b11b3599eb9f45b50a9efd722" + integrity sha512-zDRAqDSBudazdfM9zpiI30Fu9ve47htYXcGi3ln0wfKu2a7SmrT6F3VDoYONu//48V8Vz4TdCRNPjtvyRO3yBA== + dependencies: + is-absolute "^0.1.7" + isexe "^1.1.1" + +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +widest-line@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-5.0.0.tgz#b74826a1e480783345f0cd9061b49753c9da70d0" + integrity sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA== + dependencies: + string-width "^7.0.0" + +winreg@0.0.12: + version "0.0.12" + resolved "https://registry.yarnpkg.com/winreg/-/winreg-0.0.12.tgz#07105554ba1a9d08979251d129475bffae3006b7" + integrity sha512-typ/+JRmi7RqP1NanzFULK36vczznSNN8kWVA9vIqXyv8GhghUlwhGp1Xj3Nms1FsPcNnsQrJOR10N58/nQ9hQ== + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.0.tgz#1a3dc8b70d85eeb8398ddfb1e4a02cd186e58b3e" + integrity sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q== + dependencies: + ansi-styles "^6.2.1" + string-width "^7.0.0" + strip-ansi "^7.1.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@8.18.1: + version "8.18.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb" + integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w== + +wxt@~0.19.29: + version "0.19.29" + resolved "https://registry.yarnpkg.com/wxt/-/wxt-0.19.29.tgz#82d1260725b7feb2d93a53f3ab80c9f03431b126" + integrity sha512-n6DRR34OAFczJfZOwJeY5dn+j+w2BTquW2nAX32vk3FMLWUhzpv5svMvSUTyNiFq3P0o3U7YxfxHdmKJnXZHBA== + dependencies: + "@1natsu/wait-element" "^4.1.2" + "@aklinker1/rollup-plugin-visualizer" "5.12.0" + "@types/chrome" "^0.0.280" + "@types/webextension-polyfill" "^0.12.1" + "@webext-core/fake-browser" "^1.3.1" + "@webext-core/isolated-element" "^1.1.2" + "@webext-core/match-patterns" "^1.0.3" + "@wxt-dev/storage" "^1.0.0" + async-mutex "^0.5.0" + c12 "^3.0.2" + cac "^6.7.14" + chokidar "^4.0.3" + ci-info "^4.1.0" + consola "^3.2.3" + defu "^6.1.4" + dotenv "^16.4.5" + dotenv-expand "^12.0.1" + esbuild "^0.25.0" + fast-glob "^3.3.2" + filesize "^10.1.6" + fs-extra "^11.2.0" + get-port-please "^3.1.2" + giget "^1.2.3" + hookable "^5.5.3" + import-meta-resolve "^4.1.0" + is-wsl "^3.1.0" + jiti "^2.4.2" + json5 "^2.2.3" + jszip "^3.10.1" + linkedom "^0.18.5" + magicast "^0.3.5" + minimatch "^10.0.1" + nano-spawn "^0.2.0" + normalize-path "^3.0.0" + nypm "^0.3.12" + ohash "^1.1.4" + open "^10.1.0" + ora "^8.1.1" + perfect-debounce "^1.0.0" + picocolors "^1.1.1" + prompts "^2.4.2" + publish-browser-extension "^2.3.0 || ^3.0.0" + scule "^1.3.0" + unimport "^3.13.1" + vite "^5.0.0 || ^6.0.0" + vite-node "^2.1.4 || ^3.0.0" + web-ext-run "^0.2.1" + webextension-polyfill "^0.12.0" + +xdg-basedir@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-5.1.0.tgz#1efba19425e73be1bc6f2a6ceb52a3d2c884c0c9" + integrity sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ== + +xml2js@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" + integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^16.0.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^17.5.1: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zip-dir@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/zip-dir/-/zip-dir-2.0.0.tgz#c5df6e15c8f9efeb4e320377028c9f5c8277c932" + integrity sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg== + dependencies: + async "^3.2.0" + jszip "^3.2.2" + +zod-to-json-schema@^3.24.1: + version "3.24.5" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz#d1095440b147fb7c2093812a53c54df8d5df50a3" + integrity sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g== + +zod@^3.22.4, zod@^3.23.8, zod@^3.24.2: + version "3.24.3" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.3.tgz#1f40f750a05e477396da64438e0e1c0995dafd87" + integrity sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==